4

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

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

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

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

这将返回一个包含我的对象的数组,相当于:

send("string".reverse.upcase)

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

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

4

4 回答 4

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
于 2011-09-28T11:44:07.880 回答
2

在最初的问题六年后,Ruby 2.5.0 引入了Object#yield_self,然后在 Ruby 2.6 中缩短为#then

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

[...]

它执行块并返回其输出。

红宝石功能#6721

例如:

2.then{ |x| x*x }  # => 4
于 2017-10-11T04:55:34.760 回答
1

您在寻找Object.tap吗?

于 2011-09-28T11:28:07.923 回答
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 包含在标准库中

于 2014-04-15T08:48:48.623 回答