Sunday, 20 May 2007

Perl



プログラミング言語シリーズ。

最初に見たのは、USENETに投稿されたPerl 2.0だったと思います。88年あたり。Lally Wall の名前は、patch とか rn とかで既に良く知られてました。さっそく、展開して使ってみて違和感ありませんでした。awk/shell script に慣れてたのと、awk/shell script に違和感があったので、Perlを作る動機も理解できたし。

発想的には、BASIC だと思う。世代的にもBASICになじんだ世代だし。Unix APIを、全て使えるBASICが欲しいってことだよね。

最初に作ったのは、domain の定義から、named の定義ファイルを生成するプログラムだと思う。Emacs のoutline mode のファイルから、LaTeXを生成するscript は、D論を書くに使ってました。元は、awk で、a2p で変換したものが元です。

なんだが〜 Perl 5.0 で、$a->{-count} = 3 みたいなのが導入されて、連想配列ベースのオブジェクト指向プログラムが導入されます。これは、嫌いな人が多いんじゃなかろうか?僕は、実は、こういうインスタンス変数の実装が連想配列として見えてしまうってのは、嫌いじゃないです。bless で、連想配列と module を接続して、実行時にオブジェクトを構成するってのは、面白い。

実装が見えるのが嫌いなら、$a->set_count(3); みたいな感じで、accessor を作れば良い。どんなオブジェクト指向言語でも、メソッド呼び出しはハッシュ探索になるので、実は同じだし。Perl は連想配列の高速実行に命を賭けている言語なので、それに頼るのは script 言語として正しいと思う。

このあたりが嫌いで、Python/Ruby に逃げる人は多いでしょう。

Perl reference は、あんまり複雑なアクセスは書かないが、
  $album{$album}->{tracklist}->
   {sprintf("%04d,%04d",$disk,$track)} = \%song;
ぐらいは、普通に書いちゃう。

あるいは、
  my(%arg) = @_;
みたいな形で、関数の引数を連想配列で受けるというのも良くやります。こうすると、
  CardPlay::CardPileUndo->new(
   -from=>$prevSplit,
   -to=>$self,
   -at=> - ($#{$cardpile->{'-contents'}}+1));
みたいな形で、引数にキーワードを付けて、順不同にすることが出来ます。割と普通の技術です。=> の前は、quote されるので、'' は必要ありません。-つけているのは、Perl/Tkに合わせたんだと思う。Tcl がそういう仕様なんだよね。

これは、Perlがオリジナルではもちろんなくて、Common LISPとかAdaとかも、そういう機能があります。SmallTalk/Squeak も、似たように hoge from: a to: self at: 7 みたいに書けるけど、順序を変えたいと思ったら、全ての組合せを記述する必要があります。

C で、これをやりたいときは、
 struct arg { int hage, fuga; int aho; };

 void f(struct arg h) {
   printf("%d %d %d\n",h.hage,h.fuga,h.aho);
 }

 int main8() {
   f((struct arg){.fuga = 3,.aho=5});
   printf("%d\n",((struct arg){.aho=120, .hage=55}).aho);
 }
とかすることが可能。でも、そんなことをしているのは見たことがないです。
   f({.fuga = 3,.aho=5});
と、呼べると良いんだが、それは出来ない。

C++ では、型で判断して呼び出す関数を選択する Polymorphism ってのがあります。これが、wxWidget などで、絶望的にものごとを複雑にしてしまっていると思う。Polymorphism では、デフォルト値をうまく与えることが出来ないんだよね。Open/GLとかでも、関数名に引数の型を記号化して含めるハンガリアン記法を導入しているのは、Polymorphismによる弊害を避けるためだと思う。C++ では、Defaults Arguments があるのだが、呼出側で keyword が使えないのは不便。

No comments: