perl 始めました

Plagger という RSS を色々弄ったりするツールが使いたくて、でも欲しいプラグインが存在してないようなのでせっかくだし自前で書こうかと perl を始めました。
Plagger の為だけなので若干釣りタイトルな気がしないでもないのですが気にしない。

学ぶのに利用したサイト/ページ

1. Perl入門: http://www.perlplus.jp/perl/
2. 2時間半で学ぶPerl: http://qntm.org/files/perl/perl_jp.html

perl 初学者の自分としては分かりやすく書いてあって助かりました。




……で、これだけだと余りにも味気なさ過ぎるので、上記の二つを読んで perl について興味深い/意外だ/珍妙な/面白いと思った点がいくつかあったので書いてみます。

リストが平坦化される

perl では二次元に書こうとしてもリストが平らにされます。

(
 (1,2,3),
 (4,5,6),
)

このリストは

(1,2,3,4,5,6)

に直されます。

こんな風にされたらどうやって構造的な変数を作るの? と思ったらやり方はちゃんとありました。
それは次の項目に改めて。

変数

perl の格納できる変数の構造

変数
├ スカラ($)
| ├ 数字
| ├ 文字
| └ リファレンス*
├ 配列(@)
└ ハッシュ(%)

この扱う型の少なさで大丈夫なのかな、と思ってしまうのですが perler がこのままにしているので大丈夫なんでしょう。

変数はそれぞれスカラ値、配列、ハッシュの三つがあり、それぞれ別の接頭字($, @, %)を付けて扱います。

$scalar = 1;
@array  = (1,2,3,4,5);
%hash   = (key => "value");

ここで面白い事に、接頭字が違えば同名の変数を別物として扱えます。
なので、

$a = 1;
@a = (10);
%a = {0 => 100};

とやっても怒られません(別の誰かには怒られるかも知れませんが)。

リストは平坦化されてしまうので構造的な値を持てなくなってしまいますが、ここで出てくるのがリファレンスです。
リファレンスを用いると変数を参照する変数を作成できます。
\ を変数前に置いてリファレンスを得られます。

@array = (1,2,3);
$a = \@array;
$b = @{$a}[0]; # リファレンス先の配列の先頭を $b に代入します(ここでは1が代入されます)

二次元配列はこの配列のリファレンスを配列にすると作れます。
(リファレンス, リファレンス, リファレンス, ...)
というように。

変数の接頭字も同名の変数も、構造的な変数の作り方もどれも驚きでした。

戻り値

perl での戻り値は return の値か最後の値を使用する。

サブルーチンの定義は
sub name { ... }
なので、たとえば

sub hoge {
  1 + 2;
}

この中の 1 + 2 という式の計算結果が最後値のため、これが関数の戻り値になります。

もちろん他の言語のように
return 値;
を使えば好きな場所で戻り値を返せます。

return 無しに戻り値の意味を持たせるというのは、次の項目の do ブロックのようなのものには強い味方だなと思いました。

do ブロック

無名関数の呼び出しのようなこと(それともそのもの?)ができる。

do ブロックは
do { ... }
と書くと、 ... の中身が実行され結果が返ります。

print do {my $a = 1 + 2; $a;}

小さなブロックでローカル変数を使えて値が返せて羨ましい。

デフォルトの変数の省略

デフォルトの変数と、その省略というのがあり便利そうなのですが扱うのは難しそうです。

foreach を例に使います。
そのままの foreach がこれです。

foreach my $i (1..10) {
  print $i;
}

1以上10以下(1..10) の値を順番に $i へ格納して print で出力しています。

これにデフォルトの変数の省略を使うと、

foreach (1..10) {
  print;
}

んん゛? 変数はどこいった?
と言った所ですね。

foreach は格納先の変数が省略されるとデフォルトの変数 $_ に値を格納します。
そして引数の省略された print はデフォルトの変数を出力します。

たまにネットで見かけるワンライナー perl はこれをよく使っていますね。

関数呼び出しに () を付けなくても呼び出せる

関数名を書いておくだけで関数を呼び出してくれます。

sub f {
  print "Hello";
}
&f; # & が関数呼び出しの指示子

引数があっても括弧を付けなくて良くなります。

sub add5 {
  $_[0] + 5; # $_[0] が一つ目の引数を表します
}
add5 10;

一つ目の例は & を付けないと関数のプロトタイプなのか呼び出しなのか分からなくなる為 & を使います。
二つ目のは引数の存在で関数とわかるため & を使わなくても呼び出せます。

良いですね、これ。

モジュールとパッケージ、名前空間

モジュールを作る際には名前空間を自前で書いておかなければなりません。
書かないと名前空間なしに展開されます。

use Pen::Size;

というのは読み込みのパス {$PERL5LIB}/Pen/Size.pm の指定です。

上記の通りの名前空間にするには該当ファイルで

package Pen::Size;

と書く必要があります。

wantarray

サブルーチンは戻り値にリストを求められているのか、それともスカラ値を求められているのかを知ることができる。

sub ot {
  return 1 if wantarray;  # 戻り値がリストの場合
  10;
}
$a = ot;  # $a は配列ではないので 10 が返ります
@b = ot;  # @b は配列なので (1) が返ります

関数の殻の部分に書くのではなく中に書いてしまうというのは意外でした。

おわりに

俺達の冒険はこれからだ。