【问题标题】:Yield variable scope with Ruby使用 Ruby 生成变量范围
【发布时间】:2017-03-26 14:24:48
【问题描述】:

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

抱歉,如果这非常明显 - 我真的不明白代码块中带有 function(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.

根据我对代码块的理解,它显示“对于每个参数,将“我的名字是#{那个参数}”放到屏幕上。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 的呢?

【问题讨论】:

    标签: ruby scope yield


    【解决方案1】:

    根据我对代码块的理解,它显示“对于每个参数,将“我的名字是#{that argument}”放在屏幕上

    不。从字面上看,它读取“将参数'Eric'传递给方法yield_name并传递这个块”。将一个块传递给方法这一事实毫无意义。该方法可以简单地不调用它(也称为“让步阻止”)。因此,在不知道方法的实现的情况下,您不能对块调用的数量或提供的参数的值做出任何假设。

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

    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 语句,则您提供的块将被完全忽略(因此,不会打印任何内容)。但是我们确实触发了两次该块并在输出中看到了两行。

    【讨论】:

    • 这很棒。我有很多要学习的!静态值和参数值的区别有帮助。函数调用它们的代码块是我没有太多经验的东西,但现在我可以更准确地考虑它!如果我理解正确,代码块的让步将静态变量“Kim”传递到代码块本地 |n| 参数的范围内?
    • @Mr.Kennedy:是的,没错。当您执行yield "Kim" 时,将调用该块,其参数n"Kim"
    • 耶!非常感谢:D
    【解决方案2】:

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

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

    还有yields 这么称呼它:

    my_block("Kim")
    my_block(name)
    

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

    【讨论】:

    • 那么当yield("Kim")yield_name("Eric")s 块正在执行时被调用,yield(arg)s 的值被传递给块的变量值? ...我想我看到它融合在一起了,谢谢!
    • @Mr.Kennedy 我没有遵循那里的推理。当您调用yield_name("Eric") { |n| … } 时,您将"Eric"(作为name)和块传递给yield_namename 或块都不会自动使用或执行。当你yield "Kim" 时,块被执行并且"Kim" 被传递给它(name 根本没有被使用,并且可能永远不会被使用,它没有区别)。 yield name 是一个完全不同的案例,稍后会发生。
    • 便便。我还是不明白。感谢您在我挣扎时的耐心。也许使用“yield_name(name)”是a bad choice...
    • @Mr.Kennedy:“当 yield("Kim") 在 yield_name("Eric")s 块正在执行时被调用时" - 情况正好相反。 你执行yield("Kim")时块执行。如果你不让步,块就不会运行。
    • @Mr.Kennedy:这里没有递归。并且没有递归收益率参数。
    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 2022-01-17
    • 2018-04-08
    • 1970-01-01
    • 2017-04-12
    • 2021-08-27
    • 2013-11-18
    相关资源
    最近更新 更多