Perlの配列は以下のように宣言できる
my @Animals = qw/Dog Rat Rabbit Horse Cat Elephant/;
その後
my @a = @Animals;
とすれば変数@aには全く同じ値が格納されている。
ではこうしたらどうなるだろう?
my $a = @Animals;
違いは変数名の前の記号だがこれをsigil(シジル)という。
Perlはこのsigilによってどんな型の値が欲しいのかを判断してくれる。
この場合、変数$aには数値の6が格納されているが具体的には配列@Animalsの要素の数だ。
Perlは単一の値が欲しい時に配列を渡したらその配列の要素数を返す。これをスカラーコンテキストという。
逆に複数の値を要求する時をリストコンテキストという。
ちなみにこう書いたら
my ($a) = @Animals;
これはリストコンテキストと判断される。$aには配列の1番目の値が入る。
実際print演算子もリストコンテキストで値を評価している。なので
print @Animals;
とすれば
DogRatRabbitHorseCatElephant
とすべての要素を連結して出力してくれる。これは
print "Dog", "Rat", "Rabbit"...
とカンマ区切りで複数の値を渡したのと同じ事だ。
これをスカラーコンテキストで評価したい場合こう書く事が出来る。
print scalar @Animals;
これはscalar関数を呼び出し@Animalsの要素数を要求している。
結果は6だ。
文字列の中に配列を埋め込んだ場合はどうなるだろう。
print "@Animals";
今度は
Dog Rat Rabbit Horse Cat Elephant
こう出力される。先ほどとの違いは各値を半角のスペースで区切って出力しているところだ。
これはPerlの特殊変数$"に格納されている値で区切っているという事で、例えばこの値を変えてみて
$" = "\n"; print "@Animals";
こうすると
Dog Rat Rabbit Horse Cat Elephant
と、出力される。
ちなみに$,という特殊変数もあるがこちらは文字列の中で展開するのではなく。
$, = "\n"; print @Animals;
こうした時に上記と同じ結果になる。
こうしてみると文字列の中でも配列はリストコンテキストで評価されていると言えるが、ではその文字列の中で配列の要素数が欲しい時にはどうすればいいか?
普通に考えると文字列を連結すればいいと思うだろう。もしくは事前に変数に埋め込む方法もある
print "要素数は".scalar @Animals."個です";
とか
my $tmp = scalar @Animals; print "要素数は${tmp}個です";
これでもいいが、このscalar関数の呼び出し自体を文字列中に埋め込む方法がある。
書き方はこうだ。
print "要素数は@{[scalar @Animals]}個です";
こうも書ける。
print "要素数は${\(scalar @Animals)}個です";
これで同様の結果になる。
実際にこの機能はすごくありがたい機能だと思う。
文字列で出来ると言う事はヒアドキュメント中でも出来ると言う事だ。
さらには関数の呼び出しだけではなく関数の定義さえも出来てしまう。
例えば
print <<EOT; <p>要素数@{[scalar @Animals]}個</p> <ul> @{[join "\n", sub { my $op = shift; my @tmp; push @tmp, "<$op>$_</$op>" for (@_); @tmp; }->('li', @Animals)]} </ul> EOT
こうすると
<p>要素数6個</p> <ul> <li>Dog</li> <li>Rat</li> <li>Rabbit</li> <li>Horse</li> <li>Cat</li> <li>Elephant</li> </ul>
と出力される。これはヒアドキュメント中で関数を定義しその場で呼び出している。
当然こんなコードは見にくいと怒られるかもしれないが、自分しか見ないコードであれば全然いいと思う。
プログラマにとってはこういった"書き方を考える"という行為はそれほど苦ではないだろう。
むしろ変数名や関数名を考える方が鬱陶しい事に思えるのではないか。
そう、まさしくPerlはプログラミングする時に"どう書くか悩む事を楽しめる"言語なのだ。
Rubyにも同様の機能があるが、ぜひPHPにも欲しいとこだ。
カテゴリ:
トラックバック(0)
トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/28
コメントする