[英]Ruby Closures: How to return args and block as a single argument to pass to a method
Suppose I have a method that takes args and a block: 假设我有一个采用args和块的方法:
def yield_if_widget(*args, &block)
if args[0].is_a?(Widget)
block.call
end
end
I can call this method with arguments and a block: 我可以使用参数和块来调用此方法:
yield_if_widget(Widget.new) do
puts "I like widgets"
end
But what if I have another method that prepares the arguments and the block: 但是如果我有另一个方法来准备参数和块呢?
def widget_and_block
args = [Widget.new]
block = proc{ puts "I like widgets" }
[args, block]
end
And I want to be able to pass it directly to the first method: 我希望能够将它直接传递给第一个方法:
yield_if_widget(*widget_and_block)
Is this possible? 这可能吗? How?
怎么样? Assume that
yield_if_widget
is defined in a library and monkey-patching it is not an option. 假设
yield_if_widget
是在库中定义的并且猴子修补它不是一个选项。
To make ruby understand that the parameter in a call to a method is a block, a commercial and must be put in front of it. 为了让ruby明白方法调用中的参数是一个块,一个商业广告,必须放在它前面。
def widget_and_block
args = [Widget.new]
block = proc{ puts "I like widgets" }
[args, block]
end
wab = widget_and_block
# ⇓
yield_if_widget(*wab.first, &wab.last)
Oneliner (it won't return what yiw
returns): Oneliner(它不会返回
yiw
返回的内容):
widget_and_block.tap { |args, cb| yield_if_widget *args, &cb }
UPD Basically, ampersand in method call is used to say “hey, convert this to proc and use as codeblock” to ruby. UPD基本上,方法调用中的&符号用于表示“嘿,将其转换为proc并将其用作代码块”到ruby。 It's a syntax part of the language, like you have to put array content inside square brackets, not curly.
它是语言的语法部分,就像你必须将数组内容放在方括号内,而不是卷曲。 That's why an ampersand should exist in the source code.
这就是为什么源代码中应该存在&符号的原因。
On the other hand, whether you were free to modify the yield_if_widget
and remove ampersand from parameter list: 另一方面,您是否可以自由修改
yield_if_widget
并从参数列表中删除&符号 :
-def yield_if_widget(*args, &block)
+def yield_if_widget(*args, block)
the code would work as expected, since the proc instance is passed as the last parameter and calling call
method on it is very naturally permitted. 代码将按预期工作,因为proc实例作为最后一个参数传递,并且很自然地允许
call
它。
Please also note, that prepending an ampersand to the last parameter to method call forces #to_proc
method to be called on it, like in: 还请注意,将&符号添加到方法调用的最后一个参数强制在其上调用
#to_proc
方法,如:
[1,2,3].reduce &:+
#⇒ 6
The magic above works because Symbol
class has it's own implementation of #to_proc
method. 上面的魔法是有效的,因为
Symbol
类有它自己的#to_proc
方法实现。
you can't do it in one line (as far as I can tell). 你不能一行(据我所知)。 You need temporary variables.
你需要临时变量。
given these methods: 给出这些方法:
def prepare
return [4, proc { puts "called" }]
end
def run(a, &block)
puts a
block.call
end
You can pass the return values from prepare
to your method like so: 您可以将
prepare
的返回值传递给您的方法,如下所示:
i,blk = prepare()
run(i, &blk)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.