Ruby tap的变异版本——还是管道表达式的一种方式?

Ruby tap的变异版本——还是管道表达式的一种方式?,ruby,Ruby,tap将self生成传递给它的块,并返回未更改的self。我经常发现自己希望有一个版本的tap返回块的返回值,而不是self。例如: [1,2].inject(:+).tap {|x| x * 3} #=> returns 3, but I want 9 是否有任何内置方法可以实现这一点 典型的解决方案——创建一个临时本地变量来存储[1,2]的输出。注入(:+),然后将其乘以3——似乎很困难。没有内置的方法,但您可以从以下位置添加: 这就像#tap,但是#tap产生self并返回self

tap
self
生成传递给它的块,并返回未更改的
self
。我经常发现自己希望有一个版本的
tap
返回块的返回值,而不是
self
。例如:

[1,2].inject(:+).tap {|x| x * 3} #=> returns 3, but I want 9
是否有任何内置方法可以实现这一点


典型的解决方案——创建一个临时本地变量来存储
[1,2]的输出。注入(:+)
,然后将其乘以3——似乎很困难。

没有内置的方法,但您可以从以下位置添加:

这就像#tap,但是#tap产生self并返回self,as#ergo产生self但返回结果


你可以自己做

class Object
  def my_tap
    return yield self if block_given?
    self
  end
end

[1,2].inject(:+).my_tap {|x| x * 3}
=> 9

这是一个老问题,但你现在可以用它来解决。

是的,我知道,我想避免使用monkeypatching对象。是的,但金钱修补并不总是邪恶的。我喜欢@Mori的答案,虽然我同意,但在这种情况下,用一个独特的名字可能没问题。我觉得奇怪的是ruby不支持这样一个基本的概念,虽然…很有趣,Steve!不过,我不认为名称应该包含“tap”,因为它与
tap
(可能是
chain
)无关。当然,它可以是
对象的
细化
。这真的很有趣。如果我们有这种方法,我们需要
点击
?我想不出在没有块的情况下会使用这种方法。你能?(似乎需要一个块。)我不明白你所说的“返回
self
unchanged”是什么意思。例如,
{a:1}.tap{h | h[:a]=2}{a=>2}
。您可以编写
[3]。点击{a | a.replace[9]}#=>[9]
,但这只适用于数组是可变的。显然,对于像
Fixnums
这样的不可变对象,您无法做到这一点。我应该说“返回self”。与我想要的相反:“返回块返回的内容”您当然可以通过将其包装在方法中并短路返回来实现:
def doit(arr);arr.inject(:+).tap{x|return x*3};结束
。然后
doit[1,2]#=>9
。这就违背了这一点,因为我的目标是语法紧凑,以表达一个共同的想法:管道化值。我想要unix
|
。蒙基补丁似乎是唯一的方法。这只是一个观察,而不是一个建议。
class Object
  def my_tap
    return yield self if block_given?
    self
  end
end

[1,2].inject(:+).my_tap {|x| x * 3}
=> 9