1

同じ引数を指定した proc 呼び出しで毎回同じ結果が得られるかどうかを確認したいと思います。pureproc引数付きの呼び出しは無料なので、 を呼び出すたびにpureproc(1,1)同じ結果が得られます。dirtyproc引数付きで呼び出された はその環境内にバインドされているため、 と同じアリティを持っていてもpureproc、その出力は環境に依存します。

ruby-1.9.2-p136 :001 > envx = 1
=> 1
ruby-1.9.2-p136 :003 > pureproc = Proc.new{ |a,b| a+b}
 => #
ruby-1.9.2-p136 :004 > dirtyproc = Proc.new{ |a,b| a+b+envx }

呼び出された proc またはメソッドが解放されているかどうかをプログラムで判断するにはどうすればよいですか? バインディング、ローカル変数などの説明も歓迎します。

4

2 に答える 2

1

おそらく、sourcify などの gem を使用してソースを解析し、すべてのトークンを取り出して、変数であるものがあるかどうかを確認できます。ただし、これはプロシージャ/メソッド呼び出しの値が定数であるという概念とは異なることに注意してください。たとえば、コード内にTime.nowまたはRandom.newのようなものがある場合、変数を定義する必要はありませんが、呼び出すたびに変化します。また、proc が を持っている場合はどうしたいですenvx - envxか? これは一定のままですが、envx定義されていない限りエラーを返すという意味でコードに影響を与えます。

于 2012-09-25T06:20:47.000 に答える
0

うーん、トリッキーです。parameters予想される引数について通知するメソッドがあります (ラムダではなくプロシージャを使用している場合、引数がオプションであることに注意してください) 。

pureproc.parameters
=> [[:opt, :a], [:opt, :b]] 
dirtyproc.parameters
=> [[:opt, :a], [:opt, :b]]

閉じたオーバー変数の 1 つが実際に proc の戻り値を計算するために使用されているかどうかを判断するには、AST をたどることが思い浮かびます (そのための gem があります) が、面倒に思えます。私の最初のアイデアは のようなものでしdirtyproc.instance_eval { local_variables }たが、両方のクロージャーが同じ環境で閉じられるため、明らかにそれほど遠くまでは行きません...

ただし、全体的な問題は次のとおりです。何かが純粋であることを確認したい場合、そもそも環境を閉じない適切な方法にしないのはなぜですか?

于 2012-09-24T19:44:03.863 に答える