使用Ruby产生变量范围

时间:2016-11-12 13:48:10

标签: ruby scope yield

Ruby如何区分函数产生“Kim”的情况下的代码块|n|和函数调用的“Eric”情况?

道歉,如果这很明显 - 我真的不知道带有函数(arg)调用的代码块中的|n|变量究竟如何影响函数内部yield调用?

def yield_name(name)
  puts "In the method! Let's yield..."
  yield("Kim")
  puts "... now in between the yields!"
  yield(name)
  puts "Block complete! Back in the method."
end

>>> yield_name("Eric") { |n| puts "My name is #{n}." }

In the method! Let's yield...
My name is Kim.
... now in between the yields!
My name is Eric.
Block complete! Back in the method.

正如我理解代码块一样,它会读到,“对于每个参数,放到屏幕上”我的名字是#{that argument}“。Ruby如何将”Kim“传递给”那个参数“,所以它打印出”我的名字“是金“而不只是”金“?谢谢。

----------------------编辑

这是一个不太容易混淆的例子:

def double(parameter)
    yield parameter
    yield 7
end

当我调用时:

>>> double(3) { |n| puts "how? #{n * 2}" }

我明白了:

how? 6  #<-- relative to function call(arg)
how? 14 #<-- relative to internal functions yield call(arg)

那么Ruby如何知道在puts语句中使用yield 7?

2 个答案:

答案 0 :(得分:1)

您可以将块视为概念上类似于方法:

def my_block(n)
  puts "My name is #{n}."
end

yield s称之为:

my_block("Kim")
my_block(name)

换句话说,n是块的参数,它从yield获取其值,每次产生一个值时都会触发块的执行。

答案 1 :(得分:1)

  

据我了解代码块,它会读取&#34;对于每个参数,放到屏幕&#34;我的名字是#{that argument}&#34;

不。从字面上看,它读取&#34;传递参数&#39; Eric&#39;方法yield_name并传递此块&#34;。将块传递给方法这一事实并不意味着什么。该方法可以简单地不调用它(也称为&#34;屈服于阻止&#34;)。因此,您无法在不知道方法实现的情况下对块调用的数量或提供的参数值做出任何假设。

在这种情况下,我们知道实现

def yield_name(name)
  puts "In the method! Let's yield..."
  yield("Kim")
  puts "... now in between the yields!"
  yield(name)
  puts "Block complete! Back in the method."
end

在这里,我们看到每次调用yield_name都会调用其块两次。首先,使用静态值("Kim")。第二次,它只是中继其参数name。如果此处没有yield语句,则您提供的块将被完全忽略(因此,不会打印任何内容)。但我们确实触发了两次阻塞并在输出中看到两行。