Evaleval(イーバル)はいくつかのプログラミング言語が持つ、文字列を式として評価(evaluate)する関数、または複数の文をプログラム中のあるコンテキストで実行するサブルーチンである。 evalの類の機能はコンパイラ言語よりもインタプリタ言語でより一般的である。なぜならコンパイラ言語でこのような機能を実現するには、プログラム自体に言語処理系や(変数名などの)実行時情報を埋め込む必要があるからである。evalに近い機能を実現しているコンパイラ言語も存在する。 セキュリティ上のリスク信頼されないソースからのデータをevalするときには特に注意が必要である。例としてインターネット上からデータを得る data = get_data() foo = eval(data) 攻撃者がこのプログラムに例えば 適切な使用evalは非常に強力なため、経験の浅いプログラマは何でもevalを使って済ませてしまうことがある。たいてい、そのような場合には専用のより良い選択肢が存在し、コードのパースにかかる時間が節約できる。 例えば、evalは簡易テンプレートエンジンとして使われることがある。PHPでの例を示す。 $name = 'John Doe';
$greeting = 'Hello';
$template = '"$greeting, $name! How can I help you today?"';
print eval("return $template;")
この例は期待した動作をするが、前述のようにセキュリティ上の問題を抱えており、他の方法よりもはるかに遅い。より高速で安全な方法は単に eval は表計算ソフトなどの数式を評価する必要のあるアプリケーションで使われることがある。これは数式のパーサを自作するよりも手軽だが、自作や既存の専用のパーサを利用するほうがより良い。前述の問題点に加え、言語組み込みのevalはアプリケーション用にカスタマイズできないからである。 おそらく、evalの最も優れた使い道は(LISPなどでの)処理系のブートストラップや、言語の対話的な実行環境でユーザが書いたプログラムを実行することであろう。 実装インタプリタ言語ではevalは通常のコードと同じインタプリタで実装されるのがほとんどである。 コンパイラ言語ではevalを実装するために通常のコンパイラをプログラムに埋め込むこともある。また特別のインタプリタを使うこともあり、その場合はコードの重複が問題となる。 実例JavaScript, ActionScriptJavaScriptやActionScriptにおいては、evalは式の評価器と文の実行器のハイブリッドのような存在である。evalは最後に評価された式の値を返し(JavaScriptとActionScriptではすべての文は式である)、最後のセミコロンは省くことができる。 式評価器としての例: foo = 2;
alert(eval('foo + 2'));
文実行器としての例: foo = 2;
eval('foo = foo + 2;alert(foo);');
JavaScriptでのevalの使用の一例はAjaxなどにおけるJSONのパースである。しかし、現在は多くのブラウザでより特化したJSON.parseが定義されている。 ActionScriptではevalを任意の式を評価するために使うことはできない。Flash 8のドキュメントによれば、その使用は「変数、プロパティ、オブジェクト、ムービークリップの名前」を表す式に限られ、「パラメータはStringまたはオブジェクトのインスタンスへの直接の参照のどちらでもよい」[1]。 LISPLISPはevalが最初に登場した言語である。evalの実装によって、最初のLISPインタプリタが現れたのである。それ以前は、LISPの式はコンパイルされていた。しかし一度evalが実装されると、それは単純な入力・評価・出力のループ (REPL) の一部として使われるようになり、最初のLISPインタプリタの基礎を形作った。LISPの後のバージョンのevalはコンパイラとしても実装されている。 PerlPerlのevalは、文字列をプログラムとして解釈するほか、例外処理機構としても機能する。コードの塊をテストし、必要ならそれに関して警告することができる。例えば、除算において実行時エラーが発生すると # 0による除算の例外を回避する
eval { $answer = $x / $y; };
warn $@ if $@;
PHPPHPでのevalは、ほぼ、文字列中のコードをまるで echoを使った例: <?php
$foo = "Hello, world!\n";
eval('echo $foo;');
?>
値を返す例: <?php
$foo = "Goodbye, world!\n";
echo eval('return $foo;');
?>
PostScriptPostScriptの ((Hello World) =) cvx exec
は PostScript の式である PostScriptでは PythonPythonでの
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
>>> x = 1
>>> y = 1
>>> exec "x += 1; y -= 1"
>>> x
2
>>> y
0
ColdFusionColdFusionの <cfset x = "int(1+1)">
<cfset y = Evaluate(x)>
これは読み込む変数をプログラム的に選択するときなどに、特に便利である。 <cfset x = Evaluate("queryname.#columnname#[rownumber]")>
RubyRubyには式を評価するコンテキストごとに3種類のevalが存在する。
def foo
x = 1
binding
end
eval('x + 1', foo) #=> 2
class Bar
@@cvar = 10 #クラス変数
def initialize
@ivar = 5 #インスタンス変数
end
end
bar = Bar.new
bar.instance_eval('@ivar') #=> 5
Bar.class_eval('@@cvar') #=> 10
脚注
外部リンク |