ruby 将 lambda 作为块传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8162257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:30:16  来源:igfitidea点击:

Passing a lambda as a block

rubylambda

提问by heneryville

I'm trying to define a block that I'll use to pass the the each method of multiple ranges. Rather than redefining the block on each range, I'd like to create a lamba, and pass the lambda as such:

我正在尝试定义一个块,我将使用它来传递多个范围的 each 方法。我不想在每个范围上重新定义块,而是想创建一个 Lamba,并像这样传递 lambda:

count = 0
procedure = lambda {|v| map[count+=1]=v}
("A".."K").each procedure
("M".."N").each procedure
("P".."Z").each procedure

However, I get the following error:

但是,我收到以下错误:

ArgumentError: wrong number of arguments(1 for 0)
    from code.rb:23:in `each'

Any ideas what's going on here?

任何想法这里发生了什么?

回答by numbers1311407

Tack an ampersand (&) onto the argument, for example:

&在参数上加上一个和号 ( ),例如:

("A".."K").each &procedure

This signifies that you're passing it as the special block parameter of the method. Otherwise it's interpreted as a normal argument.

这表示您将它作为方法的特殊块参数传递。否则它被解释为一个正常的参数。

It also mirrors they way you'd capture and access the block parameter inside the method itself:

它还反映了您捕获和访问方法本身内部块参数的方式:

# the & here signifies that the special block parameter should be captured
# into the variable `procedure`
def some_func(foo, bar, &procedure)
  procedure.call(foo, bar)
end

some_func(2, 3) {|a, b| a * b }
=> 6

回答by Tombart

The trick is in using an &which tells Ruby to convert this argument to a Procif necessary and then use the object as the method's block. Starting from Ruby 1.9 there's a shortcut for lambda (anonymous) functions. So, you can write code like this:

诀窍是使用 an&告诉 RubyProc在必要时将此参数转换为 a ,然后将该对象用作方法的块。从 Ruby 1.9 开始,就有了 lambda(匿名)函数的快捷方式。所以,你可以写这样的代码:

(1..5).map &->(x){ x*x }
# => [1, 4, 9, 16, 25]

will take each element of the array and compute its power

将获取数组的每个元素并计算其幂

it is the same as this code:

它与此代码相同:

func = ->(x) { x*x }
(1..5).map &func

for Ruby 1.8:

对于 Ruby 1.8:

(1..5).map &lambda {|x| x*x}
# => [1, 4, 9, 16, 25]

To solve your problem you can use Array's method reduce(0is initial value):

要解决您的问题,您可以使用 Array 的方法reduce0是初始值):

('A'..'K').reduce(0) { |sum,elem| sum + elem.size }
# => 11

Passing a lambda function to reduceis a bit tricky, but the anonymous block is pretty much the same as lambda.

将 lambda 函数传递给reduce有点棘手,但匿名块与 lambda 几乎相同。

('A'..'K').reduce(0) { |sum, elem| ->(sum){ sum + 1}.call(sum) }
# => 11

Or you could concat letters just like this:

或者你可以像这样连接字母:

('A'..'K').reduce(:+)
=> "ABCDEFGHIJK"

Convert to lowercase:

转换为小写:

('A'..'K').map &->(a){ a.downcase }
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]

In the context of a method definition, putting an ampersand in front of the last parameter indicates that a method may take a block and gives us a name to refer to this block within the method body.

在方法定义的上下文中,在最后一个参数前放置一个 & 号表示一个方法可以采用一个块,并为我们提供一个名称以在方法体内引用该块。

回答by dansteren

The other answers left something un-clarified that I'd like to expand on. How do we pass an arg and a block to a method?

其他答案留下了一些我想扩展的未澄清的内容。我们如何将一个 arg 和一个块传递给一个方法?

Suppose we have a method that takes an arg and a block:

假设我们有一个接受 arg 和块的方法:

def method_with_arg_and_block(arg)
  puts arg
  yield
end

and a proc:

和一个过程:

pr = proc { puts 'This is a proc'}

The answer: It's important that you pass the proc in as an arg with an ampersand rather than appending the proc to the method (like you would do with a block).

答案:重要的是您将 proc 作为带有 & 符号的 arg 传入,而不是将 proc 附加到方法中(就像使用块一样)。

For example if you do:

例如,如果你这样做:

method_with_arg_and_block('my arg') &pr

you will get a "no block given (yield)" exception.

你会得到一个“no block given (yield)”异常。

The correct way to call this is:

正确的调用方式是:

method_with_arg_and_block('my arg', &pr)

Ruby will take care of converting the proc to a block and appending it to your method. Note: since lambdas are also procs, this will work with lambdas as well.

Ruby 将负责将 proc 转换为块并将其附加到您的方法中。注意:由于 lambdas 也是 procs,这也适用于 lambdas。

Thanks to https://medium.com/@sihui/proc-code-block-conversion-and-ampersand-in-ruby-35cf524eef55for helping me understand this.

感谢https://medium.com/@sihui/proc-code-block-conversion-and-ampersand-in-ruby-35cf524eef55帮助我理解这一点。