LoginSignup
30
29

More than 5 years have passed since last update.

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

Last updated at Posted at 2013-09-19

配列とスカラー変数

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

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];

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

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スクリプトをエラーをとって回して見ると、以下の様に表示されます。

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つ見ていきます。

# 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 ってしています。

# 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つの方法です。
なのでこれは、@hogeはただの配列です。
アロー演算子を使っていますが、これは 主に リファレンスを呼ぶ書き方です。

リファレンスは ワープホール みたいなもので、 実体へのアドレス が記されています。
なので、リファレンスを呼ぶと実体までワープして呼びに行けるって感じ...
Narutoでいうと口寄せの術とかそれに近いイメージですね( 印を結べば口寄せ動物を呼び出せる[リファレンスを呼べば実体を参照出来る]

# 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

リファレンスの中身

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

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) こう表記されるんですね。

アロー演算子

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

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

  • ハッシュへのリファレンス
$ref = \%hash;
print $ref->{name}, "\n";
  • オブジェクトの参照
$ref = new Obj;
print $ref->getName();
  • メソッド

まずはBad Know-How.

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

↓こうしたほうが良いね

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

コッチの方が自然です。

30
29
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
30
29