Hatena::ブログ(Diary)

サイド3

2008-07-02

[]まだ続く引数

いつもみてるid:perlcodesampleさんからコメントがあったのでおさらい。

 @_の中には、元の変数へのリファレンスではなくて、元の変数エイリアス(別名)が入っています。実体としては同じなんだけれど、二つの名前を持つというイメージですね。

なるほど。

だから前回やったこれで

http://d.hatena.ne.jp/lolstep/20080701/1214921039

    # そして書き換え
    $_[0] = "XYZ";

値が書き換わったってわけか。

そうなると、配列でもちゃんとやれば変わるってことかな。

#!/usr/bin/perl
use strict;
use warnings;


my @array = ("1", "2", "3", "4", "5");

print "array-> @array\n";
arg1(@array);
print "array-> @array\n";


sub arg1
{
    my @array = @_;

    print ("in sub -> @array\n");

    # そして書き換え
    @_ = ("A", "B", "C", "D", "E", "F");
}
C:\MyWorks\Perl\arg>perl arg8.pl
array-> 1 2 3 4 5
in sub -> 1 2 3 4 5
array-> 1 2 3 4 5

余裕でダメ。おかしい。

1個だけ変えてみると

#!/usr/bin/perl
use strict;
use warnings;


my @array = ("1", "2", "3", "4", "5");

print "array-> @array\n";
arg1(@array);
print "array-> @array\n";


sub arg1
{
    my @array = @_;

    print ("in sub -> @array\n");

    # そして書き換え
    @_[0] = "AAA";
}
C:\MyWorks\Perl\arg>perl arg9.pl
Scalar value @_[0] better written as $_[0] at arg9.pl line 20.
array-> 1 2 3 4 5
in sub -> 1 2 3 4 5
array-> AAA 2 3 4 5

スカラーだから@_[0]じゃなくて$_[0]で書けよって警告きたけどちゃんと書き換わる。

なんで個別だと書き換わって全体だとダメなのかなあ。

ためしに@_の個数を変えてみたりしてみる。

配列の個数とかいろいろはここを参考に。

http://d.hatena.ne.jp/perlcodesample/20080114/1200305034

#----- 配列の個数を取得 -------------

my $aryCount = @numbers; # @numbersをスカラーコンテキストで評価する

print "要素の個数 : $aryCount\n";

#----- 配列の最後の要素番号を取得 ----

print "最後の要素番号 : $#numbers\n";

print "\n";

#----- 最大値と最小値を取得

my $max = List::Util::max( @numbers );

my $min = List::Util::min( @numbers );

print "最大値 : $max\n";

print "最小値 : $min\n"

なんかスカラーにいったん入れないと取れないとか$#で取れるとかどうも馴染めないなあと思ったら、最後のやつはしっくりくる。

JavaScriptでもlengthとかcountとかそんな感じで取ってたのでそれを使ってみよう。

#!/usr/bin/perl
use strict;
use warnings;
use List::Util;

my @array = ("1", "2", "3", "4", "5");

print "array-> @array\n";
arg1(@array);
print "array-> @array\n";


sub arg1
{
    my @array = @_;

    print ("in sub -> @array\n");

	my $cnt = List::Util::max( @_ );
    print ("cnt -> $cnt\n");

    # そして書き換え
    @_ = ("1", "2", "3");

	$cnt = List::Util::max( @_ );
    print ("cnt -> $cnt\n");

    # そして書き換え
    $_[1] = "AAA";
}
C:\MyWorks\Perl\arg>perl arg10.pl
array-> 1 2 3 4 5
in sub -> 1 2 3 4 5
cnt -> 5
cnt -> 3
array-> 1 2 3 4 5

@_の個数は再定義により変わったけど、今度は値を変えたはずなのに変わってない。

もしかして再定義したから@arrayのエイリアスじゃなくなったってことかな。

ということは、もし書き換わってしまったというのなら

    @_ = ("A", "B", "C", "D", "E", "F");

こんなことしたら当然@arrayのエイリアスじゃなくなってるはずなので値が変わらないのは納得できるんだけどどうなのかなあ。

とりあえず確証は無いがそうだと今は思うことにして、後でわかったら解明するとしよう。

id:perlcodesampleさんからのコメントにもあるように

 で、my @ary = @_; とした時点で、@ary に@_の内容がコピーされます。元の引数を変更したいときは、リファレンスを渡したほうがよく、@_を直接いじるのは、あんまり推奨されないと思います。

リファレンスでわたせばいいのに直接いじる意味もないし。

というわけで時間も時間なので

 あと、my ( $ary ) = @_ でも、引数をひとつ受け取れますけれど、普通は、$_[0] か、shiftで受け取ります。複数のときは、shiftを繰り返すか、 my( $var1, $var2 ) = @_ という感じですね。

これは次回で!

perlcodesampleperlcodesample 2008/07/03 23:33  @_の中身に入っているスカラーがエイリアスなのであって、@_自体はエイリアスじゃないです。

 サブルーチンを呼んだときに、@_の中身が設定されるので、@_自体を @_ = ( 1, 2 ) 見たいに置き換えてあげても、元の値は変更されませんよ。これは ( 1, 2 )という新しいリストをメモリ上に作成してあげて@_に代入するという意味です。

 間違っても、@_ のそれぞれの要素に順番に( 1, 2 )を入れるという意味ではないです。

lolsteplolstep 2008/07/04 19:16 いつもお世話になってます。

なんかだんだんわけわかんなくなってきました。

>サブルーチンを呼んだときに、@_の中身が設定されるので、@_自体を @_ = ( 1, 2 ) 見たいに置き換えてあげても、元の値は変更されませんよ。これは ( 1, 2 )という新しいリストをメモリ上に作成してあげて@_に代入するという意味です。

ここは理解できましたが

>@_の中身に入っているスカラーがエイリアスなのであって、@_自体はエイリアスじゃないです。

ここがなんかわけわかんなくなってきました。

スッキリさせるため次のエントリで自分なりにまとめてみます。

chaichanPaPachaichanPaPa 2008/07/04 19:53 こんばんは! はじめまして。
早速なのですが、以下はイコールではないのですか?
@_ = ( 1, 2 );

$_[0] = 1;
$_[1] = 2;

lolsteplolstep 2008/07/05 16:00 はじめまして。
一応
http://d.hatena.ne.jp/lolstep/20080705/1215241002
このエントリで検証してみましたが、わたしの検証が合っていれば別物でした。
ただ、わたしはPerl初心者なので合っているかどうかは不明ですw

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。