gpt4 book ai didi

ruby - Ruby block 的问题

转载 作者:数据小太阳 更新时间:2023-10-29 08:16:50 25 4
gpt4 key购买 nike

代码有什么问题?

def call_block(n)

if n==1

return 0
elsif n== 2

return 1
else
yield
return call_block(n-1) + call_block(n-2)

end

end


puts call_block(10) {puts "Take this"}

我正在尝试使用 yield 来打印 Take this 而不是第十个斐波那契数。

我收到错误:在“call_block”中:没有给出 block (LocalJumpError)

即使是下面的代码也会抛出错误:

def call_block(n)

if n==1
yield
return 0
elsif n== 2
yield
return 1
else
yield
return call_block(n-1) + call_block(n-2)

end

end


puts call_block(10) {puts "Take this"}

最佳答案

首先,让我们稍微清理一下,以便更容易看出问题所在:

def call_block(n)
return 0 if n == 1
return 1 if n == 2

yield

call_block(n-1) + call_block(n-2)
end

puts call_block(10) { puts 'Take this' }

现在让我们来追踪一下。

我们先调用

call_block(10) { puts 'Take this' }

所以,n10, block 是 { puts 'Take this' }。由于 n 既不是 1 也不是 2,我们得到 yield,它将控制转移到 block 。

现在我们打电话

call_block(n-1)

这是

call_block(9)

请注意,我们没有使用 block 来调用它。因此,对于这个新调用,n9 并且没有 block 。同样,我们跳过前两行,来到 yield

但是没有yield 的 block ,这就是代码在这里爆炸的原因。

解决方案既明显又微妙。显而易见的部分是:问题是我们没有传递 block ,因此解决方案是我们需要传递 block 。微妙的部分是:我们如何做到这一点?

使 Ruby block 在语法上如此轻量级的原因在于它们是匿名的。但是如果 block 没有名字,我们就不能引用它,如果我们不能引用它,那么我们就不能传递它。

解决这个问题的方法是在 Ruby 中使用另一种构造,它基本上是比 block 更重量级的“代码块”概念的抽象:Proc

def call_block(n, blk)
return 0 if n == 1
return 1 if n == 2

blk.()

call_block(n-1, blk) + call_block(n-2, blk)
end

puts call_block(10, ->{ puts 'Take this' })

如您所见,这 在语法上有点重,但我们可以为 Proc 命名,从而将其传递给递归调用。

但是,这种模式实际上很常见,因此在 Ruby 中有专门的支持。如果您在参数列表中的参数名称前面放置一个 & 标记,Ruby 会将作为参数传递的 block “打包”到 Proc 对象中,并且将其绑定(bind)到该名称。相反,如果您在参数列表中的参数表达式前放置一个 & 标记,它会将那个 Proc“解包”到一个 block 中:

def call_block(n, &blk)
return 0 if n == 1
return 1 if n == 2

yield # or `blk.()`, whichever you prefer

call_block(n-1, &blk) + call_block(n-2, &blk)
end

puts call_block(10) { puts 'Take this' }

关于ruby - Ruby block 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4259652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com