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

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

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

```perl: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
```

# 親で作成したハッシュに子が要素として配列を直接追加する

```perl: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で追加する

```perl: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
```

# 理解したい

## スカラー変数(普通の変数)のリファレンス・デリファレンス

```perl: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}``の中括弧は省略できる。

```perl: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
```

理解するために、以降は省略しないで書く

## 配列のリファレンス・デリファレンス

```perl: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の括弧による振る舞いの違いとリファレンス・デリファレンス](https://qiita.com/hiyoko3/items/b7162dc65f03eab83104)


```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``を作成し、そのリファレンスを子に渡していた。
無名配列生成子``[]``を使うと最初からリファレンスだけ生成できる。

## ハッシュの要素に配列を詰める

たぶんこの書き方は間違い

```perl: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.
```

ハッシュの要素に配列を詰めるためには、そのリファレンスでなければいけない

```perl: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
```

これも無名配列生成子を使うとこうなる

```perl: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``を定義しなくていい。

## 改めて見直す

最初の例

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

完全に理解した！（してない）