よく使うのにいっつも忘れる。
親で作成&代入した要素を子で取り出す
test.pl
sub hoge
{
# 4. リファレンスを受け取る
my $test_ref = $_[0];
# 5. デリファレンスして要素を抜き出す
print(${$test_ref}{"sakura"}[0] . "\n");
}
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. 無名配列[a,b,c]を詰める
$test{"sakura"} = ["a","b","c"];
# 3. サブ関数にリファレンスを渡す
hoge(\%test);
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
a
親で作成したハッシュに子が要素として配列を直接追加する
test.pl
sub hoge
{
# 3. リファレンスを受け取る
my $test_ref = $_[0];
# 4. 要素として無名配列を詰める
${$test_ref}{"warabi"} = [1,2,3];
}
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. サブ関数にリファレンスを渡す
hoge(\%test);
# 5. 親が要素を取り出す
print($test{"warabi"}[1] . "\n");
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
2
親で作成したハッシュに子が要素として配列をpushで追加する
test.pl
sub hoge
{
# 3. リファレンスを受け取る
my $test_ref = $_[0];
# 4. 要素を詰める
push(@{${$test_ref}{"basara"}}, "D");
push(@{${$test_ref}{"basara"}}, "E");
push(@{${$test_ref}{"basara"}}, "F");
}
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. サブ関数にリファレンスを渡す
hoge(\%test);
# 5. 親が要素を取り出す
print($test{"basara"}[2] . "\n");
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
F
理解したい
スカラー変数(普通の変数)のリファレンス・デリファレンス
test.pl
sub hoge
{
my $test_ref = $_[0];
print("ref : " . $test_ref . "\n");
print("val : " . ${$test_ref} . "\n");
}
package main;
{
my $test = "abc";
hoge(\$test);
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
ref : SCALAR(0x21d6a40)
val : abc
この時、${$test_ref}
の中括弧は省略できる。
test.pl
sub hoge
{
my $test_ref = $_[0];
print("ref : " . $test_ref . "\n");
print("val : " . $$test_ref . "\n");
}
package main;
{
my $test = "abc";
hoge(\$test);
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
ref : SCALAR(0x20b1088)
val : abc
理解するために、以降は省略しないで書く
配列のリファレンス・デリファレンス
test.pl
sub hoge
{
my $test_ref = $_[0];
print("ref : " . $test_ref . "\n");
print("val : " . ${$test_ref}[1] . "\n");
}
package main;
{
my @test = ("abc","def","ghi");
hoge(\@test);
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
ref : ARRAY(0x967970)
val : def
親で配列を無名で作成する
括弧の違いによる挙動は以下が一番わかりやすかった。ありがたみの化身。
Perlの括弧による振る舞いの違いとリファレンス・デリファレンス
test.pl
sub hoge
{
my $val = $_[0];
print("ref : " . $val . "\n");
print("val : " . ${$val}[0] . "\n");
}
package main;
{
my $test_ref = ["abc","def","ghi"];
hoge($test_ref);
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
ref : ARRAY(0x65a7d0)
val : abc
1つ前のパターンでは一度、配列@test
を作成し、そのリファレンスを子に渡していた。
無名配列生成子[]
を使うと最初からリファレンスだけ生成できる。
ハッシュの要素に配列を詰める
たぶんこの書き方は間違い
test.pl
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. 配列(a,b,c)を詰める
@test{"sakura"} = ("a","b","c");
# 3. 要素を取り出す
print($test{"sakura"}[1] . "\n");
}
ハッシュの要素に「配列」を直接詰め込むことはできない。
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
Can't use string ("a") as an ARRAY ref while "strict refs" in use at test.pl line 11.
ハッシュの要素に配列を詰めるためには、そのリファレンスでなければいけない
test.pl
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. 配列(a,b,c)を詰める
my @list = ("a","b","c");
$test{"sakura"} = \@list;
# 3. 要素を取り出す
print($test{"sakura"}[1] . "\n");
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
b
これも無名配列生成子を使うとこうなる
test.pl
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. 配列(a,b,c)を詰める
$test{"sakura"} = ["a","b","c"];
# 3. 要素を取り出す
print($test{"sakura"}[1] . "\n");
}
結果
C:\Users\Ki2neudon\Downloads> perl test.pl
b
これだと"無名"のありがたみが分かる。@list
を定義しなくていい。
改めて見直す
最初の例
test.pl
sub hoge
{
# 3. リファレンスを受け取る
my $test_ref = $_[0];
# 4. 要素を詰める
push(@{${$test_ref}{"basara"}}, "D");
push(@{${$test_ref}{"basara"}}, "E");
push(@{${$test_ref}{"basara"}}, "F");
}
package main;
{
# 1. ハッシュ %test を定義
my %test;
# 2. サブ関数にリファレンスを渡す
hoge(\%test);
# 5. 親が要素を取り出す
print($test{"basara"}[2] . "\n");
}
@{${$test_ref}{"basara"}}
の部分。
-
$test_ref
はハッシュのリファレンス(アドレス)である -
%{$test_ref}
はハッシュのリファレンス(アドレス)をデリファレンスしたものである -
${$test_ref}{"basara"}
はハッシュのリファレンス(アドレス)をデリファレンスして"basara"
をキーにした要素を取り出したものである。ココに格納されているものは配列["D","E","F"]
のリファレンス(アドレス)である。 -
@{${$test_ref}{"basara"}}
はハッシュのリファレンス(アドレス)をデリファレンスして"basara"
をキーにして取り出した配列のリファレンス(アドレス)をデリファレンスしたものである!!! -
${${$test_ref}{"basara"}}[0]
書いてないけど、この場合はハッシュのリファレンス(アドレス)をデリファレンスして"basara"
をキーにして取り出した配列のリファレンス(アドレス)をデリファレンスしたものに含まれる0番目の要素である!!!
完全に理解した!(してない)