Ruby 默认块和收益

Ruby default block and yield

我正在解决以下问题:

describe "some silly block functions" do
  describe "reverser" do
    it "reverses the string returned by the default block" do
      result = reverser do
        "hello"
      end

      expect(result).to eq("olleh")
    end

根据我的理解,这应该反转一个字符串。我的代码如下:

def reverser
    yield "hello"
end

reverser do |i|
    puts i.reverse
end

这简直returns"hello"。我可能在这里遗漏了一些关于 yield、blocks 和 functions 如何相互作用的基本概念。我该如何去做我想完成的事情?

您需要在reverser中包含反转字符串的逻辑。

def reverser
  yield.reverse
end

但为什么还要费心使用块呢?用普通参数就清楚多了

def reverser(str)
  str.reverse
end

reverser('hello')  #=> olleh

如果要将要反转的字符串放入block中,则需要获取调用block的结果并进行反转。

def reverser(&block)
  block.call.reverse
end

irb(main):009:0> result = reverser do
irb(main):010:1*   "hello"
irb(main):011:1> end
=> "olleh"

答案很好而且正确,但也许仍然无济于事。

您应该从您的规格开始:

it "reverses the string returned by the default block"

那么,你的方法应该做什么就很清楚了:

def reverser
  # should reverse the string returned by the default block
end

现在让我们看看如何实现它。好的,它应该扭转一些事情。但是什么?让我们看看:

string returned by the default block

这表明我们需要执行默认块并获取其 returned 值。让我们看看 docs 怎么说:

yield - Called from inside a method body, yields control to the code block (if any) supplied as part of the method call. ... The value of a call to yield is the value of the executed code block.

所以,看来你的方法需要执行一次yield。它将执行一个块和 return 块的值 returns。所以,只需在此处放一个 yield

def reverser
  yield
end

如果你 运行 你的规范,它会抱怨 - 你会看到字符串仍然没有反转。所以,这就是您的方法要做的事情:

def reverser
  yield.reverse
end

就是这样。

我同意以上回复 - 它们最有道理。但想补充说明您的代码无法正常工作的原因以及解决方法:

expect(result).to eq("olleh")

所以根据你想要的结果 return 一个字符串。是这样做的吗?

  1. 将return设为零。当您将 put 放在方法的末尾时 - 请注意该方法将为 return nil。这是阴险的,因为有时结果不是预期的。
  2. 但你期望它 return 'olleh'
  3. 摆脱看跌期权,它应该像你期望的那样工作(未经测试)
def reverser
  yield "hello"
end

reverser do |i|
  i.reverse  # NOTE THAT THE PUTS is missing here
end

我想这就是您要找的。

编辑:请测试并告诉我,因为有些人认为我的答案完全错误!当然你不想依赖你正在使用的特定块作为设计点,但这应该让你知道为什么它不起作用

我知道已经过去一年了,但还没有得到正确的回答。

def reverser
  out = []
  yield.split.each{|word| out << word.reverse}
  out.join(" ")
end

我很确定它与范围有关