一部のプログラミング言語では、`evaluate`evalの略である` exec`は、文字列をその言語の式であるかのように評価し、結果を返す関数です。他の言語では、`exec` は、`evaluate` を含む行の代わりに、複数のコード行が含まれたかのように実行します。`exec` への入力は必ずしも文字列である必要はありません。抽象構文木( Lisp の形式など)のような構造化されたコード表現、または (Python のように) のような特殊な型である場合があります。文に相当するのは`exec`で、文字列 (または他の形式のコード) を文であるかのように実行します。Python などの一部の言語では `exec` と `exec` の両方が存在しますが、他の言語では `exec` または `exec` のいずれか一方のみが存在する場合があります。evalevalcodeevalexec
信頼できないソースからのデータを使用するevalと、セキュリティ上の脆弱性が生じる可能性があります。たとえば、get_data()関数がインターネットからデータを取得すると仮定すると、次のPythonコードは安全ではありません。
session [ "authenticated" ] = False data = get_data () foo = eval ( data )攻撃者は、文字列をデータとしてプログラムに渡すことで、認証済みキーをTrueに設定する辞書を"session.update(authenticated=True)"更新できる可能性があります。これを防ぐには、プログラムで使用されるすべてのデータをエスケープするか、潜在的に有害な関数にアクセスできないようにプログラムを実行する必要があります。sessioneval
インタプリタ型言語では、eval関数はほぼ常に通常のコードと同じインタプリタで実装されます。コンパイル型言語では、関数を使用するプログラムに、プログラムのコンパイルに使用されるコンパイラが組み込まれる場合があります。ただし、コードの重複がeval生じるため、別のインタプリタが使用されることもあります。
JavaScriptにおいて、evalは式評価器とステートメント実行器の中間のような存在です。最後に評価された式の結果を返します。
式評価器としての例:
foo = 2 ; alert ( eval ( 'foo + 2' ));ステートメント実行者としての例:
foo = 2 ; eval ( 'foo = foo + 2;alert(foo);' );JavaScriptの用途の一つとして、 JSONevalテキストの解析が挙げられます。これは、 Ajaxフレームワークの一部として使用される場合もあります。しかし、最新のブラウザは、このタスクに対してより安全な代替手段を提供しています。JSON.parse
ActionScript (Flash のプログラミング言語)では、eval任意の式を評価するために使用することはできません。Flash 8 のドキュメントによると、その使用は「取得する変数、プロパティ、オブジェクト、またはムービー クリップの名前」を表す式に限定されています。このパラメーターは、文字列またはオブジェクト インスタンスへの直接参照のいずれかです。[ 1 ]
ActionScript 3 は eval をサポートしていません。
ActionScript 3 Evalライブラリ[ 2 ]とD.eval API [ 3 ]evalは、ActionScript 3で同等の機能を作成するための開発プロジェクトでした。Adobe Flash Playerのサポート終了に伴い、両方とも終了しました。
Lispは1958年に関数を利用した最初の言語でした。eval実際、eval関数の定義が言語インタプリタの最初の実装につながりました。[ 4 ]eval関数が定義される 前は、Lisp関数はアセンブリ言語のステートメントに手動でコンパイルされていました。しかし、eval関数が手動でコンパイルされると、最初のLispインタプリタの基礎となった単純な読み込み-評価-出力ループの一部として使用されるようになりました。
Lispeval関数の後のバージョンは、コンパイラとしても実装されている。
Lisp の関数evalは、引数として評価される形式を期待します。指定された形式の結果として得られる値が、呼び出しの戻り値になりますeval。
これはLispコードの例です。
; 1、2、3 を引数として + 関数を呼び出すフォーム。; 6 を返します。( + 1 2 3 ) ; Lisp では、どのフォームも評価されることを意図しているため、; + の呼び出しが実行されました。; フォームに "' をプレフィックスとして付けることで、 ; Lisp によるフォームの評価を防ぐことができます。たとえば、( setq form1 ' ( + 1 2 3 )) ; これで form1 には、eval で使用できるフォームが含まれます。; 例: ( eval form1 ) ; eval は (+ 1 2 3) を評価し、6 を返しました。Lispは非常に柔軟性が高いことで知られており、eval関数も同様です。たとえば、文字列の内容を評価するには、まず関数を使用して文字列をLisp形式に変換しread-from-string、次にその結果の形式をに渡す必要がありますeval。
( eval ( read-from-string "(format t \"Hello World!!!~%\")" ))混乱を招く大きなポイントの一つは、形式のシンボルがどのコンテキストで評価されるかという点です。上記の例では、form1シンボル が含まれています+。このシンボルの評価によって、加算のための関数が生成されなければ、例が意図どおりに動作しません。そのため、Lisp の一部のダイアレクトでは、eval評価のコンテキストを指定するための追加パラメータを に指定できます (Python の関数のオプション引数と同様です。下記参照)。Lisp のSchemeダイアレクト (R 5 RS 以降)evalの例を以下に示します。
;; 上記の例のように、簡単なフォームを定義します。( define form2 ' ( +52 ) ) ;値: form2;; 初期コンテキスト内でフォームを評価します。;; 評価のためのコンテキストは、Scheme のスラングでは「環境」と呼ばれます。( eval form2 user-initial-environment ) ;値: 7;; 初期環境を混乱させ、+ を減算関数の名前にします。( environment-define user-initial-environment '+ - ) ;値: +;; フォームを再度評価します。;; 返された値が変わったことに注意してください。( eval form2 user-initial-environment ) ;値: 3Perlにおいて、このeval関数は式評価器と文実行器の中間のような役割を果たします。最後に評価された式(Perl プログラミングではすべての文は式です)の結果を返し、最後のセミコロンを省略することができます。
式評価器としての例:
$foo = 2 ; print eval ( '$foo + 2' ), "\n" ;ステートメント実行者としての例:
$foo = 2 ; eval ( '$foo += 2; print "$foo\n";' );Perlには例外処理メカニズムとして機能するevalブロックもあります(例外処理構文#Perlを参照)。これは、上記の文字列に対する使用法とは異なり、ブロック内のコードは実行時ではなくコンパイル時に解釈されるため、この記事で使用されている意味とは異なります。evalevaleval
PHPでは、eval文字列内のコードは、呼び出しの代わりにファイルに記述されたコードとほぼ同じように実行されますeval()。唯一の例外は、エラーが呼び出しから発生したものとして報告されeval()、return 文が関数の結果となることです。
一部の言語とは異なり、 の引数はeval、単なる式ではなく、1つ以上の完全な文の文字列でなければなりません。ただし、式を return 文に入れることで、 の「式」形式を取得できます。evalこれにより、 はevalその式の結果を返します。
一部の言語とは異なり、PHP の はeval関数ではなく「言語構造」であるため、[ 5 ]高階関数のように関数が使用できるコンテキストでは使用できません。
echo を使用した例:
<?php $foo = "Hello, world! \n " ; eval ( 'echo "$foo";' ); ?>値を返す例:
<?php $foo = "Goodbye, world! \n " ; // PHP5では動作しませんecho eval ( 'return $foo;' ); ?>Lua 5.1では、 loadstringLua コードを匿名関数にコンパイルします。
式評価器としての例:
loadstring ( "print('Hello World!')" )()評価を2つのステップで行う例:
a = 1 f = loadstring ( "return a + 1" ) -- 式を匿名関数にコンパイルprint ( f ()) -- 実行(結果「2」を出力)Lua 5.2 では、loadstring既存のload関数が推奨され、文字列を受け入れるように拡張されました。さらに、環境がアップバリューになったため、関数の環境を直接指定できるようになりました。
load ( "print('Hello ' .. a)" , "" , "t" , { a = "World!" , print = print })()PostScriptのexec演算子はオペランドを受け取ります。それが単純なリテラルであれば、スタックにプッシュバックされます。しかし、PostScript式を含む文字列を受け取ると、その文字列を実行可能ファイルに変換して、インタープリタで実行できます。例えば、次のようになります。
((ハローワールド) =) cvx execPostScript式を変換します
(ハローワールド) =これはスタックから文字列「Hello World」をポップして画面に表示し、実行可能な型にして、その後実行されます。
PostScriptのrun演算子は機能的には似ていますが、代わりにインタープリタがファイル内のPostScript式を解釈します。
(ファイル.ps)実行Pythonでは、eval関数は最も単純な形では単一の式を評価します。
eval例(対話型シェル):
>>> x = 1 >>> eval ( "x + 1" ) 2 >>> eval ( "x" ) 1このeval関数は、2 つのオプション引数 と を受け取りますglobal。localsこれにより、プログラマは式の評価のための制限された環境を設定できます。
このexecステートメント(またはexecPython 3.xの関数)は、以下のステートメントを実行します。
exec例(対話型シェル):
>>> x = 1 >>> y = 1 >>> exec "x += 1; y -= 1" >>> x 2 >>> y 0ステートメント/式を評価する最も一般的な方法は、コードオブジェクトを使用することです。これらは、compile()関数を呼び出し、コンパイルする入力の種類(" exec"ステートメント、" eval"ステートメント、または" single"ステートメント)を指定することで作成できます。
compile例(対話型シェル):
>>> x = 1 >>> y = 2 >>> eval ( compile ( "print 'x + y = ', x + y" , "compile-sample.py" , "single" )) x + y = 3D言語は静的コンパイル言語であるため、eval従来の意味での「 」文は含まれていませんが、関連する「mixin」文は含まれています。違いは、「eval」文が実行時に文字列をコードとして解釈するのに対し、「mixin」文では文字列は通常のコードのように静的にコンパイルされ、コンパイル時に既知である必要があります。例:
import std.stdio ;void main () { int num = 0 ; mixin ( "num++;" ); writeln ( num ); // 1 と出力されます。 }num++;上記の例では、「 」を直接記述した場合とまったく同じアセンブリ言語命令にコンパイルされます。mixin の引数は文字列リテラルである必要はなく、コンパイル時に評価可能な関数呼び出しを含む、文字列値を生成する任意の式を指定できます。
ColdFusionのevaluate関数を使用すると、実行時に文字列式を評価できます。
<cfset x = "int(1+1)" > <cfset y = Evaluate ( x ) >これは、ユーザーがプログラムによって読み取りたい変数を選択する必要がある場合に特に役立ちます。
<cfset x = Evaluate ( "queryname. #columnname# [rownumber]" ) >Rubyプログラミング言語のインタープリタはeval、PythonやPerlと同様の機能を提供し、スコープ(またはバインディング)を指定することもできます。
関数のバインディングを指定する以外にも、eval特定のクラス定義バインディングまたはオブジェクトインスタンスバインディング内の式を評価するために使用でき、文字列で指定された新しいメソッドでクラスを拡張できます。
a = 1 eval ( 'a + 1' ) # (2 と評価されます)# コンテキスト内での評価def get_binding ( a ) binding end eval ( 'a + 1' , get_binding ( 3 )) # (get_binding のコンテキストでは 'a' は 3 なので、4 に評価されます)class Test ; end Test . class_eval ( "def hello; return 'hello';end" ) # このクラスにメソッド 'hello' を追加Test . new . hello # "hello" と評価されるForthの標準的な実装のほとんどにはeval、EVALUATEとの 2 つのバリアントがありますINTERPRET。
Win32FORTHコード例:
S" 2 2 + . " EVALUATE \ 出力 "4"REALbasicには、実行時にREALbasicコードを実行できるRBScriptというクラスがあります。RBScriptは非常に厳密なサンドボックス化がされており、コアとなる言語機能のみが使用可能で、ユーザーは必要な機能へのアクセスを許可する必要があります。オプションで、コンテキストプロパティにオブジェクトを割り当てることができます。これにより、RBScript内のコードからコンテキストオブジェクトの関数を呼び出し、プロパティを使用できるようになります。ただし、RBScriptは最も基本的な型しか理解できないため、DictionaryやMySpiffyObjectを返す関数がある場合、RBScriptはその関数を使用できません。ユーザーは、PrintイベントとInputイベントを介してRBScriptと通信することもできます。
Microsoft のVBScript はインタプリタ型言語であり、2 つの構造があります。Evalは、ユーザー定義関数の呼び出しを含めることができる関数評価器です。(これらの関数は、グローバル変数の値を変更するなどの副作用を持つ場合があります。)Executeは、グローバル状態を変更できる 1 つ以上のコロンで区切られたステートメントを実行します。
VBScriptとJScriptは、evalコンパイル済みのWindowsアプリケーション(Evalをサポートしない言語で記述されているもの)の開発者が、Microsoft Script Controlと呼ばれるActiveXコントロールを介して利用できます。このコントロールのEvalメソッドは、アプリケーションコードから呼び出すことができます。ユーザー定義関数の呼び出しをサポートするには、Evalを呼び出す前に、AddCodeメソッドを使用してコントロールを初期化する必要があります。このメソッドは、選択した言語で定義されたユーザー定義関数のライブラリを含む文字列(または文字列リソース)を読み込みます。
Microsoft Office のプログラミング言語であるVisual Basic for Applications (VBA) は、ランタイム環境がp コードをコンパイルして実行する仮想マシン言語です。VBA の Eval は式評価のみをサポートしており、式にはユーザー定義関数とオブジェクトを含めることができます (ただし、ユーザー定義変数名は含めることができません)。なお、この評価器は VBS とは異なり、特定のユーザー定義関数の呼び出しは、VBA では VBScript の同一コードとは異なる動作をする場合があります。
Smalltalkのコンパイラクラスは標準クラスライブラリの一部であり、通常は実行時に存在するため、これらを使用してコード文字列を評価することができます。
コンパイラは「1 + 2」を評価します。クラスとメソッドの定義もメッセージ送信(クラスオブジェクトへの送信)によって実装されるため、コードの変更も可能です。
コンパイラ評価: 'オブジェクトサブクラス:#Foo'Tclプログラミング言語には、引数として指定されたソースコードを実行するコマンドがあります。Tclでは、すべてのソースコードを文字列として表現し、中括弧を引用符として用いるため、への引数は他のソースコードと同じ書式にすることができます。evaleval
set foo { while {[ incr i ] < 10 } { puts "$i の二乗は [expr $i*$i]" } } eval $foobs には、 1 つの文字列引数を取る関数がありますeval。この関数は、式評価器とステートメント実行器の両方の役割を果たします。後者の役割では、エラー処理にも使用できます。以下の例とテキストは、UNIX System V Release 3.2 Programmer's Manualに掲載されているbsman ページからのものです。[ 6 ]
文字列引数は
bs式として評価されます。この関数は、数値文字列を数値の内部形式に変換するのに便利です。evalまた、次の例のように、間接参照の簡略化された形式としても使用できます(なお、ではbs、_アンダースコアは連結演算子です)。name = "xyz" eval ( "++" _ name )これは変数をインクリメントします
xyz。さらに、
eval照会演算子 の前に を付けることで?、ユーザーはbsエラー条件を制御できます。例:?eval ( "open(\"X\", \"XXX\", \"r\")" )(ユーザーのプログラムを停止させる代わりに)「XXX」という名前のファイルが存在しない場合は、値ゼロを返します。
以下は、ラベルが存在する場合に、
gotoラベルに対して処理を実行しますL。label = "L" if ! ( ?eval ( "goto " _ label )) puterr = "ラベルなし"
evalコマンドは、オリジナルの「sh」(Bourneシェル)を含むすべてのUnixシェルに存在します。このコマンドは、すべての引数をスペースで連結し、その結果を再解析してコマンドとして実行します。– FreeBSD一般コマンドマニュアル
PowerShellでは、Invoke-ExpressionCmdlet は JavaScript、PHP、Python などのプログラミング言語の eval 関数と同じ役割を果たします。Cmdlet は、文字列の形式でコマンド パラメーターとして指定された PowerShell 式を実行し、指定された式の結果を出力します。通常、Cmdlet の出力は式の実行結果と同じ型になります。ただし、結果が空の配列の場合は、空文字列を出力します$null。結果が単一要素の配列の場合は、その単一要素を出力します。JavaScript と同様に、PowerShell では最後のセミコロンを省略できます。
式評価器としての例:
PS > $foo = 2 PS > Invoke-Expression '$foo + 2'ステートメント実行者としての例:
PS > $foo = 2 PS > Invoke-Expression '$foo += 2; $foo'1966年、IBMの対話型プログラミングシステム(CPS)は、IBM System/360 Model 50上で「修正ポーランド文字列表記で記述された式の解釈的評価」を実行するマイクロプログラム機能を導入した。[ 7 ]この機能をマイクロコーディングすると、代入文を解釈するプログラムと比較して5倍以上「大幅に」高速になった。[ 8 ]EVAL
理論計算機科学では、eval とapply は厳密に区別されるのが一般的です。evalは引用符で囲まれた文字列を呼び出し可能な関数とその引数に変換するステップと理解され、apply は指定された引数セットで関数を実際に呼び出すステップです。この区別は、関数型言語や、 LISPやSchemeのようなラムダ計算に基づく言語で特に顕著です。例えば、Scheme では、eval と apply の区別は次のようになります。
( eval ' ( f x ) )式(fx)を評価する場合、
( f (リストx )を適用)ここで、関数fは引数xで呼び出されます。
evalとapplyは、 SICPで説明されているLispの評価の本質であるeval-applyサイクルの相互依存する2つのコンポーネントです。[ 9 ]
圏論では、eval射を用いて閉じたモノイド圏を定義します。例えば、関数を射とし、直積を積とする集合の圏は、閉圏であるデカルト圏を形成します。ここで、eval (正確にはapply ) とその右随伴であるカリー化は、単純型付きラムダ計算を構成し 、これは閉圏の射として解釈できます。