LoginSignup
4
3

More than 3 years have passed since last update.

Perlの括弧による振る舞いの違いとリファレンス・デリファレンス

Posted at

個人メモも兼ねる。

perl 難しくないですか?難しいですよね。

この記事のターゲットユーザー

Perlよく分からんけど納期の都合上手っ取り早く文法を覚えたい

  • perl がよく分からないけど案件の中で利用されているためコードを読み解く必要がある
  • 変数名三つもあるじゃん。$, %, @ ってなんぞ?
  • リファレンス?デリファレンス?
  • [], {}, () で振る舞いが違う?なんで?

解説

※独自解釈しているところとか、口語的に説明するためかみ砕いた文章となるので間違ってたらご指摘ください。

変数

変数宣言 説明
$*** 別名スカラー変数、なんでも入れられる。アドレスを参照しているだけで実体は持っていない
%*** ハッシュ変数。実体を持つ
@*** 配列変数。実体を持つ

基本的に$使っておけばいいんじゃないですかね。明確に配列が入るとかハッシュが入るとか決まっていたら%とか@とか使う、みたいな。

リファレンス・デリファレンス

  • リファレンス => アドレスを参照した変数を宣言すること
  • デリファレンス => アドレスの中身を見よう

括弧・ふるまい

まず名前がそれぞれにあります。

  • [](記号の名前はブラケット) => 無名配列生成子
  • {}(記号の名前はブレース) => 無名ハッシュ生成子
  • ()(記号の名前は丸括弧) => リスト

です。へー

無名生成子を利用すると変数にはリファレンスが代入されます。

my @array1 = ('A', 'B', 'C');
my $array2 = [ 'A', 'B', 'C' ];

print @array1, "\n";
# => ABC
print $array2, "\n";
# => ARRAY(0x557f87a3b650)

# ちなみに、以下もリファレンス参照となります。
my $_array = ('A', 'B', 'C');
print $_array, "\n";
# => ARRAY(0x55da203f2650)

無名生成子を利用した際に実態が欲しい場合はデリファレンスを利用しなければなりません。たぶんここがperlの最初の壁でしょう。

my $array2 = [ 'A', 'B', 'C' ];
print @$array2, "n"; # または @{ $array2 }
# => ABC
print $$array2[0], "n"; # 要素は文字列なので参照するときは $演算子を利用する。
# => A

my $hash1 = { hoge => 'hoge1', fuga => 'fuga1' };
print %$hash1; # または %{ $hash1 }
# => hogehoge1fugafuga1

print $$hash1{hoge}; # 要素は文字列なので参照するときは $演算子を利用する。
# => hoge1

ここで、値を取り出すときにデリファレンスをいちいち書いているとネストした値を取り出すときに非常に不便です。

そのため、perlにはアロー演算子によるアドレス参照機能が提供されています。

my $nest1 = {
  hash => {
    'test1' => 'test1 dayo',
    'test2' => 'test2 dayo',
  },
  array => [ 'hoge', 'fuga' ]
};

# test1 dayo を取り出したい
# デリファレンスさせた書き方
print ${ %{ $nest1 }{hash} }{test1}, "\n";
# => test1 dayo

# アロー演算子
print $nest1->{'hash'}->{'test1'}, "\n";
# => test1 dayo

# hoge を取り出したい
# デリファレンスさせた書き方
print ${ @{ $nest1 }{array} }[0], "\n";
# => hoge

# アロー演算子
print $nest1->{'array'}->[0], "\n"; # $nest1->{'array'}[0] でもよい
# => hoge

最後に

アドレスの参照について分かっていれば、リファレンス周りもそこまで苦労せず理解できるかと思いますが、perl独自の挙動で詰まる人も中にはいるんじゃないかと思います。

hashの要素をデリファレンスして取得したいときに %{***}{要素名}と書くとkey, valueの両方が取得されてしまうのは、内部的にはリストで構造を持っているからとかなのでしょうか?よくわかりません。

参考

Perl - リファレンスの説明(1): かなり分かりやすい

4
3
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
4
3