0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Perlのハッシュと配列とリファレンスと無名と

Posted at

よく使うのにいっつも忘れる。

親で作成&代入した要素を子で取り出す

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"}}の部分。

  1. $test_ref はハッシュのリファレンス(アドレス)である
  2. %{$test_ref} はハッシュのリファレンス(アドレス)をデリファレンスしたものである
  3. ${$test_ref}{"basara"} はハッシュのリファレンス(アドレス)をデリファレンスして"basara"をキーにした要素を取り出したものである。ココに格納されているものは配列["D","E","F"]のリファレンス(アドレス)である。
  4. @{${$test_ref}{"basara"}} はハッシュのリファレンス(アドレス)をデリファレンスして"basara"をキーにして取り出した配列のリファレンス(アドレス)をデリファレンスしたものである!!!
  5. ${${$test_ref}{"basara"}}[0] 書いてないけど、この場合はハッシュのリファレンス(アドレス)をデリファレンスして"basara"をキーにして取り出した配列のリファレンス(アドレス)をデリファレンスしたものに含まれる0番目の要素である!!!

完全に理解した!(してない)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?