返回Ruby中对象的yield的方法

时间:2011-09-28 11:03:35

标签: ruby object block yield chainability

Ruby中是否有一个返回传递给对象的块内容的方法?

例如,如果我有一个想要放入数组的对象怎么办?

在一个理想的世界里,我们会做(我正在寻找的):

"string".reverse.upcase.something{ |s| send(s) }

将使用我的对象返回一个数组,相当于:

send("string".reverse.upcase)

如果我的对象开始时是不可链接的,并且在更复杂的场景中会变得混乱。

因此something方法将返回块的评估,如Array#map,但仅返回一个元素。

4 个答案:

答案 0 :(得分:4)

我不知道内置这样的东西,但你可以自己轻松做到:

class Object
  def something(&block)
    block.call(self)
  end
end

p "foo".something { | o | [o] }
p 23.something { | x | p x; 42 }

给出

["foo"]      # object "foo" put into an array
23           # object handed to block
42           # something return block's result

答案 1 :(得分:1)

您在寻找Object.tap吗?

答案 2 :(得分:1)

我有时希望标准库中有类似的功能。例如,该名称可以是withwith_it

(使用新名称重复以前的代码)

class Object
  def with_it(&block)
    block.call(self)
  end
end

使用示例:

x = [1, 2, 3, 4, 5].map {|x| x * x }.with_it do |list|
   head = list.unshift
   list << head * 10
   list.join " / "
end

相反:

list = [1, 2, 3, 4, 5].map {|x| x * x }
head = list.unshift
list << head * 10
x = list.join " / "

虽然后者更容易理解,但前者的好处是保留变量listhead作用域,而x的作业在我看来更明确(作业)必须将x插入到代码的最后一行)。如果代码是更大方法的一部分,那么范围界定将是一个不错的选择。

使用with_it的另一个选择是将代码放在一个单独的方法中。例如:

def mult_head_and_join(list)
    head = list.unshift
    list << head * 10
    list.join " / "
end

x = mult_head_and_join [1, 2, 3, 4, 5].map {|x| x * x }

不知道在这里结束什么,但我想我会投票支持将with_it纳入标准库

答案 3 :(得分:1)

在原始问题发布六年后,Ruby 2.5.0引入了 Object#yield_self ,然后在Ruby 2.6中缩短为 #then

 class Object
   def yield_self(*args)
     yield(self, *args)
   end
 end
     

[...]

     

执行块并返回其输出。

     

Ruby Feature #6721

例如:

2.then{ |x| x*x }  # => 4