配列とかいろいろ

仕事とかそれなりに忙しいので毎日はやれないけどコツコツと。
というわけで、この辺で実際になんか作っていく方向にいかないとモチベーション的にもあれなので、頻繁に使うであろう基本的なことを一通りやって次のステップにいくことにした。

とりあえず配列は使うよね

配列の基礎はもうやったので、よく使うであろう動的配列的な使い方をやってみる。

http://d.hatena.ne.jp/perlcodesample/20080127/1201418278

配列への追加と配列の要素の取得

* push関数 --- 配列の末尾へ追加
* pop関数 --- 配列の末尾の要素を取得
* unshift関数 --- 配列の先頭へ追加
* shift関数 ---配列の先頭の要素を取得
* splice関数 --- 複数要素の追加、取り出し、位置を指定しての追加、取得が可能
* これらの関数は、配列自体に変更を加える

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


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "A" );

# push
push @array, "Z";
my $cnt = $#array;
print "\@array[$cnt]-> $array[$cnt]\n";

# pop
my $last = pop @array;
print "$last\n";

# unshift
unshift @array, 0;
print "\@array[0]-> $array[0]\n";

# shift
my $first = shift @array;
print "$first\n";
C:\MyWorks\Perl\array>perl array1.pl
@array[8]-> Z
Z
@array[0]-> 0
0

JavaScriptからみると、なんでメソッドじゃないのかなあと思ったけど、これがPerl式なのなら仕方ない。
どうも括弧がない書き方に違和感ありまくりでどうしようかと思ったら、括弧付きでもうまくいくみたいだ。

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


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "A" );

# push
push(@array, "Z");
my $cnt = $#array;
print "\@array[$cnt]-> $array[$cnt]\n";

# pop
my $last = pop(@array);
print "$last\n";

# unshift
unshift(@array, 0);
print "\@array[0]-> $array[0]\n";

# shift
my $first =  shift(@array);
print "$first\n";

print "@array\n";
C:\MyWorks\Perl\array>perl array2.pl
@array[8]-> Z
Z
@array[0]-> 0
0
1 2 3 4 5 10 11 A

やっぱこっちのほうが落ちつく。

というところで今日は時間切れ。
まあコツコツとやるとしよう。

@_とはなんなのか

id:perlcodesampleさんからコメントをもらったので整理するためまとめてみる。

まず@_ってそもそもなんなのか。
引数の入った配列らしいのでそれを検証。

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


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

arg1(@array);

my $str1 = 123;
my $str2 = "ABC";
arg2($str1, $str2);


sub arg1
{
	my $cnt = @_;
	print ("in arg1 cnt -> $cnt\n");
}

sub arg2
{
	my $cnt = @_;
	print ("in arg2 cnt -> $cnt\n");
}
C:\MyWorks\Perl\arg>perl arg11.pl
in arg1 cnt -> 5
in arg2 cnt -> 2

ちゃんと配列だった。

で、配列の要素はスカラーなので1つ1つにアクセスする場合は$を付けろと。

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


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

arg1(@array);

my $str1 = 123;
my $str2 = "ABC";
arg2($str1, $str2);


sub arg1
{
	my $cnt = @_;
	my $arr0 = $_[0];
	my $arr1 = $_[1];
	print ("in arg1 cnt -> $cnt\n");
	print ("in arg1 arr0 -> $arr0\n");
	print ("in arg1 arr1 -> $arr1\n");
}

sub arg2
{
	my $cnt = @_;
	my $str0 = $_[0];
	my $str1 = $_[1];
	print ("in arg2 cnt -> $cnt\n");
	print ("in arg2 str0 -> $str0\n");
	print ("in arg2 str1 -> $str1\n");
}
C:\MyWorks\Perl\arg>perl arg12.pl
in arg1 cnt -> 5
in arg1 arr0 -> 1
in arg1 arr1 -> 2
in arg2 cnt -> 2
in arg2 str0 -> 123
in arg2 str1 -> ABC

ここまではOK。

次に

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

これが問題。
いまいち理解できなかったけど別名だから同じものを指してると言う意味でいいのかな。要はCで言えば@_の中身が引数と同じアドレスを指してるってことのはず。
だとすれば引数のアドレスとサブルーチンの中の@_は同じアドレスを指していて、myで代入した値は@_の値のコピーなのでアドレスは別になるはず。
というわけで実験。

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


my $str = "123";

print "str-> $str\n";
print "str-> " . \$str . "\n";
arg1($str);
print "str-> $str\n";

sub arg1
{
	my $str = $_[0];
	print "\$_[0]-> " . \$_[0] . "\n";
	print "str-> " . \$str . "\n";
	print ("in arg1 str -> $str\n");
	$str = "ABC";
	$_[0] = "XYZ";
}
C:\MyWorks\Perl\arg>perl arg13.pl
str-> 123
str-> SCALAR(0x18328bc)
$_[0]-> SCALAR(0x18328bc)
str-> SCALAR(0x1853648)
in arg1 str -> 123
str-> XYZ

予想通りの結果。
サブルーチンの引数のアドレスと、サブルーチン内の引数のアドレスが同じ。
コピーした値を変更しても変わらないけど、引数自体を変更したらアドレスが同じだから変わると。
要はサブルーチンの引数自体は参照渡しであって、ローカル変数に代入した時点で値渡しみたいになると。
だけどid:perlcodesampleさんの言ってる意味と同じ認識でいいのかなあ。

配列でも同様のはず。

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


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

print "array-> @array\n";
print "array[0]-> " . \$array[0] . "\n";
print "array[1]-> " . \$array[1] . "\n";
arg1(@array);
print "array-> @array\n";

sub arg1
{
	my $cnt = @_;
	print ("in arg1 cnt -> $cnt\n");
	my $str0 = $_[0];
	my $str1 = $_[1];
	print "\$_[0]-> " . \$_[0] . "\n";
	print "\$_[1]-> " . \$_[1] . "\n";
	print "str0-> " . \$str0 . "\n";
	print "str1-> " . \$str1 . "\n";
	$str0 = "ABC";
	$str1 = "DEF";
	$_[0] = "UVW";
	$_[1] = "XYZ";

}
C:\MyWorks\Perl\arg>perl arg14.pl
array-> 1 2 3 4 5
array[0]-> SCALAR(0x275f50)
array[1]-> SCALAR(0x276004)
in arg1 cnt -> 5
$_[0]-> SCALAR(0x275f50)
$_[1]-> SCALAR(0x276004)
str0-> SCALAR(0x18534a8)
str1-> SCALAR(0x185349c)
array-> UVW XYZ 3 4 5

予想通り。

で、問題は@_にリストを代入した場合にそのアドレスが変わっていれば

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

これの意味がわかるはず。
というわけで実験。

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


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

print "array-> @array\n";
print "array[0]-> " . \$array[0] . "\n";
print "array[1]-> " . \$array[1] . "\n";
arg1(@array);
print "array-> @array\n";

sub arg1
{
	my $cnt = @_;
	print ("in arg1 cnt -> $cnt\n");
	print "\$_[0]-> " . \$_[0] . "\n";
	print "\$_[1]-> " . \$_[1] . "\n";

	@_ = ("A", "B", "C", "D", "E");
	print "\$_[0]-> " . \$_[0] . "\n";
	print "\$_[1]-> " . \$_[1] . "\n";

	$_[0] = "UVW";
	$_[1] = "XYZ";

}
C:\MyWorks\Perl\arg>perl arg15.pl
array-> 1 2 3 4 5
array[0]-> SCALAR(0x275f50)
array[1]-> SCALAR(0x276004)
in arg1 cnt -> 5
$_[0]-> SCALAR(0x275f50)
$_[1]-> SCALAR(0x276004)
$_[0]-> SCALAR(0x185355c)
$_[1]-> SCALAR(0x1853550)
array-> 1 2 3 4 5

予想通り。

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

これやった時点で新しくリストが作成されて@_に代入され、元のアドレスが変わってしまうため書き換えたところで変わらないと。

てことで検証できたと思うんですがどうですか?

まだ続く引数

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

これは次回で!

引数

リファレンス再び

前回のこれで

http://d.hatena.ne.jp/lolstep/20080629/1214734023

リファレンスが何たるものかを大雑把に理解したわけだけども、肝心の無名配列やハッシュをやってなかったが

http://d.hatena.ne.jp/perlcodesample/20080201/1201884772
http://d.hatena.ne.jp/perlcodesample/20080217/1203233280

ここ読んで大体理解したのでそれでよしとする。じゃないと先に進めない。

引数いろいろ

http://d.hatena.ne.jp/perlcodesample/20080604/1212591180

### 引数の3とおりの受け取り方
# (1) my $num = $_[0]
# (2) my $num = shift;
# (3-1) my ( $num1, $num2 ) = @_;
# (3-2) my @num_list = @_;

* 引数は、暗黙的に、@_ に代入されています。
* @_ から、引数を取り出して、変数に格納するには、上記の4つの方法があります。
* わたしは、リスト代入を使うことが多いです。引数がひとつのときは、shift関数を、よく使います。

@_ってなんぞと思って調べたら特殊変数らしい。
そういえばはるか昔にPerlを勉強しようと思った時、わけのわからない記号が多く意味不明すぎて断念したトラウマがよみがえってきた。

http://www.rfs.jp/sb/perl/02/07.html

特殊変数 @_ は渡された値のリファレンスになっています。ですから、 @_ の値を変更すると、引数として指定された変数の値も変更されることになります。

あ、そうなの?
だったらリファレンスを引数としてわたしたらリファレンスのリファレンスになるってこと?
ここでもCのポインタのポインタとかいうトラウマがよみがえってきたが気にしないことにしておく。

というわけで実験。

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


my $str = "ABC";
my @array = ("1", "2", "3", "4", "5");
my $hash = {
    Key1 => "AA",
    Key2 => "BB",
};

print "str-> $str\n";
arg1($str);
print "str-> $str\n";

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


sub arg1
{
    # (1)で受け取ってみる
    my $str = $_[0];

    print ("in sub -> $str\n");

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

sub argr2
{
    # (1)で受け取ってみる
    my @array = $_[0];

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

    # そして書き換え
    $_[0] = ("A", "B", "C", "D", "E");
}
C:\MyWorks\Perl\arg>perl arg1.pl
Useless use of a constant in void context at arg1.pl line 41.
Useless use of a constant in void context at arg1.pl line 41.
Useless use of a constant in void context at arg1.pl line 41.
Useless use of a constant in void context at arg1.pl line 41.
str-> ABC
in sub -> ABC
str-> XYZ
array-> 1 2 3 4 5
Undefined subroutine &main::arg2 called at arg1.pl line 18.

無駄なことはやめろというエラーが豪快に返ってきたところをみると、どうやら配列やハッシュは@_の個々の引数にはなっていない模様。
スカラーだけは引数の個数分入るってことなのかなあ。

というわけで配列やハッシュを引数にする方法を探すと

http://d.hatena.ne.jp/perlcodesample/20080605/1212675666

こうやればいいらしい。

もう1回。

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


my $str = "ABC";
my @array = ("1", "2", "3", "4", "5");
my %hash = (
    Key1 => "AA",
    Key2 => "BB",
);

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

print ("hash -> $hash{Key1}\n");
arg2(%hash);
print ("hash -> $hash{Key1}\n");


sub arg1
{
    my @array = @_;

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

    # そして書き換え
    @_ = ("A", "B", "C", "D", "E");
}

sub arg2
{
    my %hash = @_;

    print ("in sub -> $hash{Key1}\n");

    # そして書き換え
    @_ = (
        Key1 => "YY",
        Key2 => "ZZ",
    );

}
C:\MyWorks\Perl\arg>perl arg2.pl
array-> 1 2 3 4 5
in sub -> 1 2 3 4 5
array-> 1 2 3 4 5
hash -> AA
in sub -> AA
hash -> AA

今度はうまくいったが書き変わっていない。
そんな気は薄々してたけど、サブルーチン内で代入してる時点で値コピーになっているんだろうな。

次にリファレンスをわたしてみる。

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


my $str = "ABC";

print "str-> $str\n";
arg1(\$str);
print "str-> $str\n";


sub arg1
{
    # (1)で受け取ってみる
    my $str = $_[0];

    print ("in sub -> $$str\n");

    # そして書き換え
    $$str = "QQQ";
    $_[0] = "XYZ";
}
C:\MyWorks\Perl\arg>perl arg3.pl
str-> ABC
in sub -> ABC
str-> QQQ

リファレンスをわたしたのでリファレンスのリファレンスに対して書き換えればいいのはわかってたけど、引数のほうを直で書き換えるのはどうすんだろうなあ。
$$_[0]とか無理だとわかってやってみたがやはりダメだった。
そんなことする必要がないのはわかってるがなんか気になる。

配列のリファレンス。

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


my @array = ("1", "2", "3", "4", "5");
my %hash = (
    Key1 => "AA",
    Key2 => "BB",
);

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


sub arg1
{
    my @array = @_;

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

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

なにも考えずボーっと受けてたけど、リファレンスでわたしてるんだからスカラーで受けなきゃダメだった。

#!/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 ("なぜかだめ -> @$array\n");

    my @array1 = ("1", "2", "3", "4", "5");
    my $ref_array = \@array1;
    print ("こっちはうまくいく -> @$ref_array\n");

    # そして書き換え
    $array[2] = "A";
}
C:\MyWorks\Perl\arg>perl arg5.pl
array-> 1 2 3 4 5
Can't use string ("1") as an ARRAY ref while "strict refs" in use at arg5.pl line 17.

なんかよくわからないエラーがでた。
ちなみにそこをコメントにすると一応意図した動作になる。

C:\MyWorks\Perl\arg>perl arg5.pl
array-> 1 2 3 4 5
こっちはうまくいく -> 1 2 3 4 5
array-> 1 2 A 4 5

ちゃんと値を書きかえられてるところをみると、リファレンスとしてわたっているのは間違いないと思うが一応確認。

#!/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 ("@_\n");

}
C:\MyWorks\Perl\arg>perl arg6.pl
array-> 1 2 3 4 5
ARRAY(0x36db0)
array-> 1 2 3 4 5

ちゃんとリファレンスだった。

なんでか全くわからないので再度ここをみてみると

http://d.hatena.ne.jp/perlcodesample/20080604/1212591180

my $num = $_[0] # @_ の最初の要素をを指定
my $num = shift; # shift 関数で、 @_ の先頭を切り出す
my ( $num1, $num2 ) = @_; # リスト代入を使って、スカラー変数に代入
my @num_list = @_; # 配列に代入

「リスト代入を使って、スカラー変数」に代入と書いてあるのが妙に引っかかった。

http://d.hatena.ne.jp/perlcodesample/20080606/1212767708

この辺みてもやはりリスト代入とやらで受け取っている。

とりあえず使ってみる。

#!/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 ("@_\n");

	print "array-> @$array\n";

}
C:\MyWorks\Perl\arg>perl arg7.pl
array-> 1 2 3 4 5
ARRAY(0x36db0)
array-> 1 2 3 4 5
array-> 1 2 3 4 5

おお取れた。

ただいまいち理解できない。

http://www.wafu.ne.jp/~ton/web/perl/perl_01.htm

# $home[0] = "aaa";   …1個ずつ代入
# @home = ("aaa" , "bbb" , "ccc");   …リスト代入
# ("aaa" , "bbb" , "ccc") = @home;   …配列からスカラー変数に値をセット
# ($aaa, $bbb) = ($bbb, $aaa); …値が入れ替えられる。なんと、こんなことがっ!

ここみてなんとなくイメージわいて来たけど、@_はリストだからスカラーで受けるときはリスト代入しないとダメってこと?

http://d.hatena.ne.jp/perlcodesample/20080605/1212675666

* 引数をサブルーチンに渡すときは、スカラーであろうと、配列であろうと、ハッシュであろうと、リストとして@_に代入されて、サブルーチンに渡されます。
* Perlのサブルーチンの特徴のひとつは、「可変個引数をリストとして受け取る」ということです。引数の個数をあらかじめ定義しなければならない言語( C や Java ) を学習した人から見ると、不思議なものに見えるかもしれません。

ということで、今回はリファレンスわたしにしたためスカラーで受け取らなきゃならなかったけど、これが配列をわたして配列でうけるのなら悩む必要は無かったってことなんだろうか。

とにかく今回はいまいち理解できてないかなあ。しかもまだ引数は終わってないし。
というわけで問題積み残しのまま次回へ続く。

リファレンス

次何しようかなと思っていろいろみてたらこんな記述があって

$ref_array = [1, 2, 3, 4, 5];

こんなのみたことないぞと思って調べてみたらリファレンスというものだった。

http://d.hatena.ne.jp/perlcodesample/20080201/1201884772

配列のリファレンス

* リファレンスとは、配列の入っているメモリの位置を指すもの
* C言語を知っているなら、「アドレス演算ができないポインタ」だと考える。
* Javaを知っているなら、「参照」だと考える。

リファレンスとリファレント

* 指されるほうをリファレントと呼び、指すほうをリファレンスと呼ぶ。

配列のリファレントの作成

* my $numbers_ref1 = \@numbers ;
* @の前に、\をつけると、配列のリファレントを作成できる。
* \@numbersがリファレントで、$numbers_ref1がリファレンス。

直接配列のリファレントを作成する

* my $numbers_ref2 = [ 1, 2, 3, 4 ];
* リストを [ ] でくくると、配列のリファレントになる。
* そして、そのリファレントを、リファレンス $numbers_ref2で指している。

配列の要素の参照

* $numbers_ref2->[0]
* 配列のリファレンス->[ 要素番号 ]

要はCのポインタみたいなもんらしい。
昔Cをちょろっとだけやったことがあるので大体の概念はわかってると思うんだが、こんなところでまた出会うとは思わなかった。

ここをみるとわかりやすい。

http://tech.bayashi.jp/archives/entry/perl/2008/002065.html

今回はここを参考にやってみる。

http://www.rfs.jp/sb/perl/02/10.html

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


my $str = "ABC";
my $ref_str = \$str;
print "スカラー リファレンス -> $ref_str\n";
print "スカラー 中身 -> $$ref_str\n";

my @array = (1, 2, 3, 4, 5);
my $ref_array = \@array;
print "配列 リファレンス -> $ref_array\n";
print "配列 中身 -> @$ref_array\n";

my %hash = (key1 => "VAL1",
			key2 => "VAL2"
			);
my $ref_hash = \%hash;
print "ハッシュ リファレンス -> $ref_hash\n";
print "ハッシュ 中身 -> %$ref_hash\n";
C:\MyWorks\Perl\ref>perl ref1.pl
スカラー リファレンス -> SCALAR(0x1832414)
スカラー 中身 -> ABC
配列 リファレンス -> ARRAY(0x1853d10)
配列 中身 -> 1 2 3 4 5
ハッシュ リファレンス -> HASH(0x18533c8)
ハッシュ 中身 -> %HASH(0x18533c8)

ハッシュはそのままで中身を出せないようだ。

要素へのアクセス。

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


my @array = (1, 2, 3, 4, 5);
my $ref_array = \@array;
print "配列 要素 -> $ref_array->[0]\n";
print "配列 要素 -> $ref_array->[1]\n";


my %hash = (key1 => "VAL1",
			key2 => "VAL2"
			);
my $ref_hash = \%hash;
print "ハッシュ 要素 -> $ref_hash->{key1}\n";
print "ハッシュ 要素 -> $ref_hash->{key2}\n";
C:\MyWorks\Perl\ref>perl ref2.pl
配列 要素 -> 1
配列 要素 -> 2
ハッシュ 要素 -> VAL1
ハッシュ 要素 -> VAL2

リファレンス経由で中身を書き換える。

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


my $str = "ABC";
my $ref_str = \$str;
print "スカラー 中身 -> $$ref_str\n";
$$ref_str = "XYZ";
print "スカラー 中身 -> $$ref_str\n";


my @array = (1, 2, 3, 4, 5);
my $ref_array = \@array;
print "配列 要素 -> $ref_array->[0]\n";
$ref_array->[0] = 9;
print "配列 要素 -> $ref_array->[0]\n";
print "配列 中身 -> @$ref_array\n";


my %hash = (key1 => "VAL1",
			key2 => "VAL2"
			);
my $ref_hash = \%hash;
print "ハッシュ 要素 -> $ref_hash->{key1}\n";
$ref_hash->{key1} = "VAL9";
print "ハッシュ 要素 -> $ref_hash->{key1}\n";
C:\MyWorks\Perl\ref>perl ref3.pl
スカラー 中身 -> ABC
スカラー 中身 -> XYZ
配列 要素 -> 1
配列 要素 -> 9
配列 中身 -> 9 2 3 4 5
ハッシュ 要素 -> VAL1
ハッシュ 要素 -> VAL9

サブルーチンもリファレンスがあるということでみてみたら

http://d.hatena.ne.jp/lolstep/20080621/1214043186

これでやった無名関数がまさにそれだった。
そういえばCも関数ポインタがあったしなるほどなと。

そうなると、サブルーチンの引数に配列わたしたり出来るなというわけでやってみようと思ったが、まだサブルーチンに引数をわたすのをやってなかった。

というわけで次はサブルーチンへの引数のわたしかたの巻。

Diablo III

http://www.4gamer.net/games/008/G000817/20080628004/

http://www.blizzard.com/diablo3/

いまでもDiabloの感動は覚えている。
あの頃のPCゲーのネットワーク対戦が出来るものといえばFPSDOOM系かレースゲーくらいしかなかったが、そこに彗星のごとく現れたMOというジャンルのDiabloはあっという間に全世界を虜にし、インターネット黎明期のまだWebsiteをホームページと言っていた時代のPCゲー関係のsiteは軒並みDiablo関係になっていった。

何より斬新だったのが、LAN対戦もさることながらbattle.netを使用しての全世界のユーザとの対戦、もしくは協力プレーだった。
Diabloが斬新だったことの1つに、死ぬと装備していたアイテムをその場にばらまくというシステムだったため、生き返るたびにアイテム回収に向かわなければならないことだった。これは本当に斬新で、普通のゲームであれば死んでも痛くも痒くもなかったが、アイテムをばらまくということは他人に拾われる可能性もあり、尚且つ回収しないでログアウトしようものならそのアイテムはロストしてしまうということがキャラクターの死を特別なものにしていった。

そのアイテムにしてもDiabloのシステムは秀逸で、後発のゲームに多大な影響を齎す事になるアイテムゲーの走りとなった。
Diabloではアイテム名に色を付けることにより、マジック・レア・セット・ユニークと4種類に分け、収集する楽しみを持たせた。
また、アイテムにはPREFIX・SUFFIXの修飾詞が付き、中でもOBSIDIAN・THE ZODIACと付いたものは物によってはユニークを遥かに超える性能ため、夜な夜なダンジョンに潜る人が増えた。

そしてもう1つ、ゲーム設定にもよるが、一緒にいるプレイヤーに攻撃出来ると言う事があった。FPSであれば基本的に対人戦を目的としたものなので別に普通であったが、MOというジャンルが珍しかったこともあり、今まで協力していたプレイヤーが珍しいアイテムが出た途端、もしくは装備しているプレイヤーを目にした瞬間に攻撃してくるということが多々あった。これがPKの走りだと思われる。
LANで取得したアイテムをそのままbattle.netで使用できたためチートも横行したが、一緒にやってるプレイヤーが普通の人かPKかを見極めるというのもある種の楽しみでもあった。

こうして後のMOに多大な影響を及ぼしたDiabloは数年後にDiablo2として発売されるも、Diablo後に発売されたUOやEQでも有名なMMOというジャンルに押され、ヒットはするもののDiabloを超えるほどの人気は出なかったと思う。

その後Blizzardは、StarCraftWarcraftというRTSのヒット作を出し、WarcraftのMMO版であるWoWが世界的ヒットを遂げるわけだが、今でもDiablo人気は根強く、今回のDiablo3の発売を心待ちにしていたユーザも数多くいた。

そしていよいよDiablo3というわけで、前作のDiablo2から約8年の歳月を経ているがその期待は膨らむばかり。
昔のようにゲームに費やす時間は少なくなったが、またあの頃の感動が味わえると信じて、来るその日を楽しみにしておく。