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