[LSP42] Perl
(この記事はLISP Implementation Advent Calendar 4日目のためのエントリです。)
PerlでLISPを作りました。
https://github.com/zick/PerLisp

動機
今年の春、訳あって42個のプログラミング言語でLISP処理系を実装することになりました。これはその6つ目です。
Perlという言語を選んだのは同僚からRを推薦された時に、私がPerlと聞き間違えたのがきっかけだったような気がします。
まるでCのような安心感
私はPerlをほとんど書いたことがなかったのですが、ウェブサイトのカウンタや掲示板を書くのによく使われていた、だれでも気軽に書ける「チャラチャラした言語の筆頭格」と認識していました。でもいざ触ってみたら、変数は宣言するし、セミコロンをちゃんと書かないといけないし、ifやforのあとの括弧も省略できないし、意外とチャラチャラしていませんでした。むしろCのような安心感がありました。
一番驚いたのは「参照」の存在です。Perlと言えばなんでも無駄にコピーされるという認識だったのに、参照のおかげで安心してプログラムが書けます。あと、Perlといえば変数の前に $ を付けますが、配列だと @ で ハッシュだと % を付けるという面倒なルールがありますが、参照を使うと、常に $ しか使わなくていいというのも良かったです。参照の dereference にも $ を使うので、非常にお金の臭がするプログラムが書けます。
sub makeCons {
my ($a, $d) = @_;
# 中括弧{}を使えるとハッシュの参照が得られる
return { tag => 'cons', car => $a, cdr => $d };
}
sub pairlis {
my ($lst1, $lst2) = @_;
my $ret = $kNil;
while ($$lst1{tag} eq 'cons' && $$lst2{tag} eq 'cons') { # dereference してから tag にアクセス
$ret = makeCons(makeCons($$lst1{car}, $$lst2{car}), $ret);
$lst1 = $$lst1{cdr}; # cdr にも参照が入っているはずなので参照がコピーされる
$lst2 = $$lst2{cdr}; # 実体はコピーされない
}
return nreverse($ret)
}
まるでCと違う不安感
Perlを高級なC言語と思うと、悪くないんじゃないかと思いましたが、サブルーチンの引数の文法だけは意味が分かりません。
sub makeNumOrSym {
my ($str) = @_; # なにこれ......
if ($str =~ /^[+-]?\d+$/) { # これはまあいいや
return makeNum($str + 0);
}
return makeSym($str);
}
なんなんですか。 @_ というのは。Perl好きの人に文句を言ったら「shiftとか$_[0]とかもあるよ」と言われましたが、引数には名前がないとあとで読めなくなるじゃないですか。まあ、私はそう主張しながら x という名前の引数を作ったりするのですが。
小学生並みの感想
楽しかったです。でも、Perl好きの人から「ぜんぜんPerlっぽくない」と言われたので、私が書いたのはいわゆるPerlとは違う何かである可能性が高いです。
真珠と心中… 幼稚園児並みの子供ギャグ