web-dev-qa-db-ja.com

Rubyの「eval」はいつ正当化されますか?

" 'eval'は厄介なことになっていますか? "これに影響を与えました:

ほとんどの人はevalが悪いことに同意し、ほとんどの場合、よりエレガントで安全な代替品があります。

だから私は尋ねたかったのです:evalが頻繁に誤用されている場合、それは言語機能として本当に必要ですか?それは善よりも悪を行っているのでしょうか?

個人的に、私が役立つと思う唯一の場所は、設定ファイルで提供されている文字列を補間することです。

編集:この質問の目的は、evalが唯一または最良の解決策である場合に、できるだけ多くの実際のケースを取得することです。したがって、「言語がプログラマーの創造性を制限するべきである」という方向に進まないでください。

Edit2:そして私がevalと言うとき、もちろん私はevaling文字列を参照し、Rubyブロックをinstance_evalまたはclass_evalに渡さない。

26

私が知っている唯一のケース(「この文字列があり、それを実行したい」以外)は、ローカル変数とグローバル変数を動的に処理することです。 Rubyには、ローカル変数とグローバル変数の名前を取得するメソッドがありますが、これらの名前に基づいて値を取得または設定するメソッドがありません。AFAIKを実行する唯一の方法は、evalを使用することです。

他の使用法はほぼ間違いなく間違っています。私は第一人者ではなく、他に誰もいないと断言することはできませんが、誰かが「これには評価が必要です」と言った他のすべてのユースケースを見て、そうでない解決策を見つけました。

ちなみに、ここではstring evalについて話していることに注意してください。 Rubyには_instance_eval_もあり、レシーバーのコンテキストで実行するには文字列またはブロックのいずれかを取ることができます。このメソッドのブロック形式は高速で安全で非常に便利です。

23
Chuck

それはいつ正当化されますか?合理的な代替手段がない場合に言います。私は代替案を考えることができない1つの使用法を考えることができました:irb、あなたが十分に深く掘ったら(workspace.rb、興味があれば私のコピーの80行目あたり)evalを使用して入力を実行します:

def evaluate(context, statements, file = __FILE__, line = __LINE__)
  eval(statements, @binding, file, line)
end

それは私にはかなり合理的なように思えます-実行するように求められた瞬間まで、実行する必要のあるコードが具体的にわからない状況です。ダイナミックでインタラクティブなものが法案に適合しているようです。

15
Mike Woodhouse

Evalが存在する理由は、必要なときに、本当に必要なときに、代替手段がないためです。結局のところ、創造的なメソッドのディスパッチでできることはそれほど多くなく、ある時点で任意のコードを実行する必要があります。

言語に危険な機能があるからといって、それが本質的に悪いことであるとは限りません。言語がそのユーザーよりも多くを知っていると推定するとき、それは問題があるときです。

危険のないプログラミング言語を見つけたとき、あまり役に立たないものを見つけたと私は主張します。

評価はいつ正当化されますか?実用的な言葉で言えば、あなたがそう言うとき。それがあなたのプログラムであり、あなたがプログラマーである場合は、パラメーターを設定します。

10
tadman

eval()には、他のものを使用して(AFAIK)達成できない非常に重要なユースケースが1つあります。それは、バインディングに対応するオブジェクト参照を見つけることです。

ブロックが渡されたが、(何らかの理由で)バインディングのオブジェクトコンテキストにアクセスする必要がある場合は、次のようにします。

obj = eval('self', block.binding)

以下を定義することも役立ちます。

class Proc
    def __context__
        eval('self', self.binding)
    end
end
6
horseyguy

主にドメイン固有言語用のIMO。

" Rubyの評価オプション "はJayFieldsによるInfoQの記事です。

5
Diego Dias

evalはツールであり、本質的に善でも悪でもありません。それがあなたが達成しようとしていることのための正しいツールであると確信しているときはいつでもそれは正当化されます。

3
Bryan Oakley

一般に、evalは、任意のコードを実行する場合に便利な言語機能です。これはまれなことですが、独自のREPLを作成しているか、何らかの理由でRubyランタイムをエンドユーザーに公開したい場合があります。それが発生する可能性があり、それが機能が存在する理由です。言語の一部(グローバル変数など)を回避するためにそれを使用している場合は、言語に欠陥があるか、言語の理解に欠陥があります。 evalを使用しますが、言語をよりよく理解するか、別の言語を選択します。

注目に値するのはRuby特にinstance_evalおよびclass_eval他の用途があります。

2
olleicua

Evalのようなツールは、実行時と「コンパイル」時のコードの評価に関するものです。 Rubyを起動したときのコードを知っていますか?次に、おそらくevalは必要ありません。コードは実行時にコードを生成していますか?次に、おそらくそれを評価する必要があります。

たとえば、再帰下降パーサーに必要なメソッド/関数は、解析される言語によって異なります。アプリケーションがそのようなパーサーをオンザフライで構築する場合は、evalを使用するのが理にかなっているかもしれません。一般化されたパーサーを作成することもできますが、それはそれほど洗練されたソリューションではない可能性があります。

" Schemeでletrecをプログラムで入力します。マクロまたはeval? "は、Schemeでのevalについて投稿した質問であり、その使用はほとんど避けられません。

2
z5h