まだ続く引数

いつもみてる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 ) = @_ という感じですね。

これは次回で!