スゲい簡単なPerl入門 - 8thDay　リファレンス　リファレント　デリファレンス Perl  Beginner  配列 リファレンス スカラー アロー演算子 分かりづらいところの備忘録

# 配列とスカラー変数

Perlで配列の操作をするときにムムッ？ってなったところを備忘録に残します。
慣れるとなんでもないんですが、なれるまでは何がおかしいのかもよくわからないのでして。

```pl
use strict;
use warnings;

my @test1 = ("abc", "efg", "hij");
my $test2 = ["abc", "efg", "hij"];

warn @test1[0];
warn @test1->[0];
warn $test1[0];
warn $test1->[0];

warn @$test2[0];
warn @$test2->[0];
warn $test2[0];
warn $test2->[0];
```

このまま動かしてもまぁエラーが出るのでます。

```pl
perl test.pl

# warn $test1->[0];
Global symbol "$test1" requires explicit package name at array.pl line 10.

# warn $test2[0];
Global symbol "@test2" requires explicit package name at array.pl line 14.
```

表示の通り、この変数で宣言はしていないので、エラーとなります。
Perlだと@ や % や $ の区別が面倒くさいです。

・ **$hoge はスカラー変数(scalar) **
⇒ *scalar [名] 数量*
⇒ **数量を表す変数**
⇒ **変数なので1つの要素（配列、ハッシュ、リファレンスも）を指します**

・ @hoge は配列(array)
・ %hoge はハッシュ・連想配列(hash)
で、 **↑これらの1要素を出したいときはスカラーを使う**
*だって1つの要素を指しているから* (自分でそう解釈していますが、違うのかも....xmx;; )


上のperlスクリプトをエラーをとって回して見ると、以下の様に表示されます。

```pl
Scalar value @test1[0] better written as $test1[0] at array.pl line 7.
Using an array as a reference is deprecated at array.pl line 8.
Using an array as a reference is deprecated at array.pl line 13.
---------- at array.pl line 6.
abc at array.pl line 7.
abc at array.pl line 8.
abc at array.pl line 9.
---------- at array.pl line 11.
abc at array.pl line 12.
abc at array.pl line 13.
abc at array.pl line 15.
```

# リファレンスとリファレントと、ときどき配列

1つ1つ見ていきます。

```pl
# my @test1 = ("abc", "efg", "hij");
# warn @test1[0];
Scalar value @test1[0] better written as $test1[0] at array.pl line 7.
```

配列の要素を指定するときは、 **$hoge[num]** とします。
理由は *個別の値を指しているからScalar* ってしています。

```pl
# my @test1 = ("abc", "efg", "hij");
# warn @test1->[0];
Using an array as a reference is deprecated at array.pl line 8.
```

**『配列をリファレンスとして使ってますが、それは推奨されません。あ、array.plの8行目のことですけどね』**

my @hoge = ();というのは[配列の初期化の1つの方法](http://www.perlplus.jp/perl/array/index5.html)です。
なのでこれは、@hogeはただの配列です。
アロー演算子を使っていますが、これは **主に** リファレンスを呼ぶ書き方です。

リファレンスは *ワープホール* みたいなもので、 **実体へのアドレス** が記されています。
なので、リファレンスを呼ぶと実体までワープして呼びに行けるって感じ... 
Narutoでいうと[口寄せの術](https://www.google.co.jp/search?q=%E5%8F%A3%E5%AF%84%E3%81%9B%E3%81%AE%E8%A1%93&hl=en&authuser=0&source=lnms&tbm=isch&sa=X&ei=RKM6Upq3LMyplQWr-IGIDQ&ved=0CAkQ_AUoAQ&biw=974&bih=739&dpr=1)とかそれに近いイメージですね（ *印を結べば口寄せ動物を呼び出せる[リファレンスを呼べば実体を参照出来る]* ）

```pl
# my $test2 = ["abc", "efg", "hij"];
# warn @$test2->[0];
Using an array as a reference is deprecated at array.pl line 13.
```

$test2 = []; は配列のリファレンスの初期化の方法です。（$hoge = {}; はハッシュのリファレンスの初期化）
なので、$test2 はリファレンスで、 ["abc", "efg", "hij"] が実体（リファレントといいます）となります。

**@$test2** はリファレンスである **$test2 をデリファレンスしています** 。つまり、 **ダイレクトに実体を取ってきています** 。 *（口寄せの術でいうと印を結ぶんじゃなくって、直で捕まえてくるぜ！って感じ？です^_^;）*

なので配列の実体なのにアロー演算子を使って配列の要素をしていするのはおかしいよねーといって warn が表示されているということです。
ですが、結局は warn なので、プログラムが止まるわけではなく、Perlさんが良きように計らって下さってなんとかなります`,､('∀\`) '`,､ ←これ罠orz

# リファレンスの中身

ちなみに、下みたいにテストしてみました。

```pl
warn @test1;    # => abcefghij
warn $test2;     # => ARRAY(0x7b62c8)
warn @$test2;  # => abcefghij
warn \$test2;    # => REF(0x78e320)
```

@test1, @$test2 の様に配列は、その中身が返されます。
*warn では文字列が結合されて返されるんですね(意識してなかった...)*

$test2 はリファレンスです。 **ARRAY(0x9s45c3)** リファレンスってこんな感じなんですね。
このアドレスが指しているのが、@$test2の中身というわけですね。

\test2はおまけ。リファレンスのリファレンスを作ってみました。配列やハッシュの@,%の前に **\** をつけてもリファレンスになるようです。
なので、 **\@test1** は@test1のリファレンスです。
リファレンスのリファレンスは **REF(0x78e320)** こう表記されるんですね。

# アロー演算子

**->** は中置の被参照演算子。
**右側が [...] か {...}の形の添字であれば、左側は配列かハッシュへのリファレンス**です。
また、 **右側はメソッド名かメソッド名を持ったスカラ変数で、左側はオブジェクトかクラス名** になります。

# リファレンスの使い方 メソッド

+ ハッシュへのリファレンス

```pl
$ref = \%hash;
print $ref->{name}, "\n";
```

+ オブジェクトの参照

```pl
$ref = new Obj;
print $ref->getName();
```

+ メソッド

まずはBad Know-How.

```pl
my @hoge; # そのままの配列
foreach (@fuga) {
  @hoge->[$i]->{$_->{kore}} = $info # アロー演算子で配列の要素を呼び出すことも出来るんですね （@hoge[$i]{$_->{kore}}が正しいはず）
}
return \@hoge; # リファレンスを返します
```

↓こうしたほうが良いね


```pl
my $hoge = []; # リファレンス初期化
foreach my $tmp (@fuga) { # 今回は関係ないですけど、特殊変数 $_ の使用はオススメしません。
  $hoge->[$i]->{$tmp->{kore}} = $info
}
return $hoge;
```

コッチの方が自然です。