将一个块作为关键字参数传递

3

是否有可能(如果可以,如何)在Ruby方法中将块作为关键字参数传递?

基本上我想要做的是:

pippo(even: {|n| n+1 }, odd: {|n| n-1})

将该方法定义为如下

def pippo(even: , odd:)
  even? ? even.yield(self) : odd.yield(self)
end

谢谢


5
请注意,when 是 Ruby 中的关键字 - Stefan
谢谢您指出这个问题。正如您所想象的那样,示例代码仅用于演示,我并不打算创建一个 when 方法。 - Sig
1
发布问题后仅15分钟就选择答案!这很糟糕,不好(在我看来)。快速选择不仅可能会阻碍其他回答的出现,而且对于那些仍在回答问题的人来说(至少有两个),在问题发布后不久就看到勾选标记闪烁有点令人沮丧。 - Cary Swoveland
2个回答

5
不,这是不可能的。块不是对象,你不能将它们作为参数传递,除非作为块参数。它们是一种轻量级的语法和语义结构,仅允许作为消息发送的块参数。块的轻量级基于一个事实,即最多只能有一个块,因此它不需要被命名和/或绑定到参数。
然而,你可以传递多个Proc或lambda。毕竟,Proc和lambda像任何其他对象一样,所以你可以像传递任何其他对象一样将它们作为参数传递。
pippo(even: -> n { n+1 }, odd: -> n { n-1 })

def pippo(even: , odd:)
  if even? then even.(self) else odd.(self) end
end

实际上,这允许您传递 任何 响应于 call 的对象,例如一个 Method

pippo(even: 1.method(:+), odd: 1.method(:-))

1.method(:succ) is not equivalent to -> (n) { n + 1 } - Stefan
当然,这是个愚蠢的笔误。我把我尝试的两个不同的例子搞混了。 - Jörg W Mittag
一个微小的不同:其中一个调用了n + 1,另一个调用了1 + n,但这个例子显然是关于整数的,所以没关系。 - Stefan
1
啊,你说得对。- 不是可结合的。我还太早了。 - Jörg W Mittag

4
如果您想提供多个块,则需要将它们通过Proc传递,或使用lambda构造声明它们:
when(
  even: -> (x) { x+1 },
  odd: -> (x) { x-1 }
)

你也可以使用 proc { ... }lambda { ... } 来声明它们,这是相同的旧式声明方式。

1
可以,但我建议修正误导性措辞。 :) - Sergio Tulentsev
1
顺便问一下,既然有proc { ... },为什么还要使用 Proc.new { ... }? :) - Sergio Tulentsev
1
很久以前,Kernel#procKernel#lambda的别名,因此返回一个lambda。然后它被更改为基本上执行def proc(&blk) Proc.new(&blk) end。但是,如果您不知道您的代码将在哪个Ruby版本上运行,您必须避免使用Kernel#proc,因为您无法知道它会做什么。学习Ruby的Rubyist在2003年之前就因此避免使用Kernel#proc,尽管那时已经淘汰了返回lambda的Ruby版本。 - Jörg W Mittag
1
@SergioTulentsev:是的,但在1.8中它执行的操作与1.9+中不同(返回一个lambda而不是普通的Proc),因此任何在1.8和1.9并行使用的时期学习Ruby的人都倾向于避免使用它。 - Jörg W Mittag
1
@JörgWMittag:啊,感谢这个历史课!我自己在2008年开始接触Ruby。 :) - Sergio Tulentsev
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接