Erlangのevalってこうやるのか

erl_evalのモジュールのドキュメントにはサンプルが無いので困っていたが、2D in erlangを読んでイメージがつかめた。

1> {ok, Tokens, _}=erl_scan:string("1 + 1.").
{ok,[{integer,1,1},{'+',1},{integer,1,1},{dot,1}],1}
2> {ok,[Expression]} = erl_parse:parse_exprs(Tokens).
{ok,[{op,1,'+',{integer,1,1},{integer,1,1}}]}
3> erl_eval:expr(Expression,erl_eval:bindings(erl_eval:new_bindings())).
{value,2,[]}

つまり、式のstringをtokenizeしてparseして評価(expr)するのだ。その際に適当な環境をbindできる。bindを現在の状態に限定すれば、次のようなevalが定義できて、eval("1 + 1.")は2である。

eval(Expr)->
 {ok, Tokens, _}=erl_scan:string(Expr),
 {ok,[Expression]} = erl_parse:parse_exprs(Tokens),
 {value, Ret, _} = erl_eval:expr(Expression ,erl_eval:bindings(erl_eval:new_bindings())),
 Ret.

実行例。返り値だけが利用できる。内部のbinding(変数Kに設定された関数とか)は外に滲みだしてこない。

1> S = ev:eval("K = fun(X) -> X + 3 end.").
#Fun<erl_eval.6.13229925>
2> S(3).
6
3> K.
* 1: variable 'K' is unbound