0

请帮助我理解为什么以下工作。

class Dog
  def bark
    "woof"
  end
end

bark_string = Dog.new.bark
puts bark_string                   # "woof" - a string at this point
ref_to_bark = -> { bark_string }   # the string a moment ago is now the method again
ref_to_bark.call                   # "woof"

为什么在 proc/lambda 中包装对方法的引用会返回对原始方法的引用?这让我很困惑。

4

3 回答 3

4

它没有。ref_to_bark只是返回bark_stringbark不调用该方法。

于 2012-06-01T15:15:56.163 回答
3

Ruby 中的 Lambda(以及块和过程)是闭包;这意味着在与定义的 lambda 相同的范围内可用的局部变量可以在 lambda内部访问。例如:

foo = 42
l = lambda{ p foo }
l.call()
#=> 42

以上不应该比这段代码有效的事实更令人惊讶:

x = 17
[1,2,3].map do |n|
  n+x # Whoa, you can use _x_ here?!
end
#=> [18,19,20]

当你做这样的事情时,它会稍微令人惊讶:

def make_adder( x )
  ->(y){ x+y }
end
add10 = make_adder(10)
z = add10.call(32)     #=> 42

同样,局部变量x(传递给方法的参数)被 lambda “封闭”,它的值被保留以供每当调用 lambda 时参考。

因此,在您的示例中,lambda 只是“捕获”bark_string变量并稍后返回其值。您的方法永远不会被第二次调用。


请注意,闭包捕获变量本身,而不仅仅是变量引用的对象:

x = "hello"
y = x         # reference the same _object_
l = ->{ x }   # close over the _variable_ itself
x = "world"   # change the variable to point to a new object

p y,          #=> "hello"     (same object as the original)
  l[]         #=> "world"     (new object)
于 2012-06-01T15:24:30.760 回答
0

使用 -> 定义的 lambda 称为 lambda 字面量。有时称为 stabby lambda。以下也将返回相同的结果。

ref_to_bark = lambda { bark_string }

或者

ref_to_bark = lambda { "woof" }
于 2012-06-01T15:19:32.810 回答