12

ルビ初心者の質問です。このコードを変更する最も簡単な方法は何ですか?ただし、ブロックを完全にそのままにして、副作用を排除しますか?

x = lambda { |v| x = 2 ; v}
x.call(3)
#=> 3
x
#=> 2

これは、私の問題を説明するために考案できる最も単純な例であるため、「割り当てを削除する」または「Proc を x に割り当てない」は、私が探しているものではありません。

元の囲んでいるスコープに影響を与えずに割り当てることができる Proc (またはラムダ) にローカル変数を設定したいと考えています。ブロックをラップするクラスまたはモジュールを動的に作成することもできますが、そのような基本的なことにはやり過ぎのようです。

私がやろうとしていることと同等のPython:

def x(v):
  x = 2  # this is a local variable, what a concept
  return v
4

2 に答える 2

28

場合によっては、それが望ましい動作です。

total = 0
(1..10).each{|x| total += x}
puts total

しかし、偶発的であり、たまたま同じ名前を持つ外部変数をいじりたくない場合もあります。その場合、パラメーターのリストの後にセミコロンとブロック ローカル変数のリストを続けます。

x = lambda{|v; x| x = 2; v}
p x.call(3) #3
p x #<Proc:0x83f7570@test1.rb:2 (lambda)>
于 2013-05-22T20:07:22.800 に答える
6

この理由は、ラムダがその定義スコープ (呼び出しスコープではない) にバインドされており、特にローカル変数を含む完全なクロージャであるためですx。ここで本当に必要なのは、特定のバインディングなしで受け渡して呼び出すためのバインドされていない proc です。これは、設計上、Ruby が非常に簡単に実行できるものではありません (eval では可能ですが、これはブロックではなく単なる文字列ステートメントです)。Proc、ラムダ、およびブロックはすべて、定義されているスコープにバインドされています。レキシカル スコープは、クラス、モジュール、およびメソッドに対してのみ確立されます。ブロック/プロシージャ/ラムダ/その他のものではありません。

そもそも、Python ではラムダでの代入さえ許可されていないことに注意してください。

于 2013-05-22T19:43:54.760 に答える