2D
use strict use Acme::ICFP2006::2D::Parser; my $f = Acme::ICFP2006::2D::Parser->parse("2d/mult.2d"); my $a = 3; my $b = 4; my $ans = $f->{modules}->{mult}->call(toIntExp($a), toIntExp($b)); print $ans->str; sub toIntExp{ my $a = shift; my $str = "Inl " x $a . "Inr ()"; return Acme::ICFP2006::2D::Exp->new($str); }
実行結果
Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inr ()
出来た。
ちなみに、mult.2dは、以下の通り。
,..............................|...................................., :plus | : : *==================* | : -->!send [(W,S),(W,E)]!--------#--------------------+ : : *==================* | | : : | | | : : | v v : : | *==============* *============* : : | !case N of S, E!--->!send [(N,E)]!------- : | *==============* *============* : : | | : : | v : : | *========* *================* : : +------------------->!use plus!------>!send [(Inl W,E)]!--- : *========* *================* : ,..................................................................., ,..............................|....................................,
- mult |
- *=================* |
-
- >!send[(W,S),(W,E)]!---------#-------------------+ :
- *=================* v v
- | *==============* *=================*
- | *==============* *=================*
- | |
- v |
- *==========* |
- !split(N,N)!--------------#------------+
- *==========* | |
- | | |
- | v v
- | *========* *========*
- *========* *========*
Perlにおけるtry catch
最近はJavaを書くことが多かったので、偶にPerlを書くとついついはまりがち。
Perlにおいてエラーなんかをトラップするための方法として、evalがあります。
http://perldoc.perl.org/functions/eval.html
で、まず一つ目としてこのevalはあくまで「関数」であって、構文ではありません。具体的にいうならば、
a = 1 / 0;
というものに対して、try catchをするのであれば、Javaならばこうすればいいわけです。
try{ a = 1 / 0; }catch(Exception e){ }
Perlの場合、同様の方法として、eval{}; if($@){}というのがありますが、この場合、evalの後ろのBLOCKの後に、必ずセミコロンが必要です。ifの後ろには要りません。どれだけ長いBLOCKであっても、セミコロンを付け忘れるとエラーです。
次に、もう一つの問題として、returnというのがあります。例えば長い関数なりメソッドがあったとして、この関数に後からエラートラップを導入するとします。その際に、
sub hoge{ eval{ #do something die; #do something return $a; }; print $@ if($@); }
としてしまうと、$aは結局returnされません。return $aの返る先は、あくまでeval文です。evalの返り値が$aになるので、これをちゃんと変数で受けてやって、その上でreturnしてやる必要があります。
ということで、2Dの実装で一番はまった部分でした。