7

有时在编写 Ruby 时,我发现自己想要一个pipe方法,类似于tap但返回调用块的结果self作为参数,如下所示:

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

some_operation.pipe { |x| some_other_operation(x) }

..但到目前为止,我还没有设法找出它的名字,如果它存在的话。它存在吗?

如果没有,我知道我可以用猴子补丁对象来添加它,但是,你知道,那很糟糕。除非有一个出色的,保证永远不会冲突(以及描述性和简短)的名称,否则我可以使用它......

4

3 回答 3

12

这种抽象在核心中不存在。我通常称它为as,它简短且具有声明性:

class Object
  def as
    yield(self)
  end
end

"3".to_i.as { |x| x*x } #=> 9

Raganwald通常在他的帖子中提到抽象,他将其称为.

所以,总结一下,一些名字:pipe, as, into, peg, thru.

于 2012-10-11T22:00:07.670 回答
2

Ruby 2.5引入了 Object.yield_self,这正是您正在使用的管道运算符:它接收一个块,将 self 作为第一个参数传递给它,并返回评估该块的结果。

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

示例用法:

"Hello".yield_self { |str| str + " World" }
# Returns "Hello World"

You can also read a little more about it in the following blog posts:

  1. Explains the difference with Rails' try and Ruby's tap methods
  2. Some very nice examples of using yield_self to simplify code
于 2018-04-18T18:45:29.017 回答
0

这是我用来链接对象的技术。除了我不重新开课外,几乎和上面一样Object。相反,我创建了一个Module我将使用它来扩展我正在使用的任何对象实例。见下文:

module Chainable
  def as
    (yield self.dup).extend(Chainable)
  end
end

我已经定义了这个方法来禁止可变方法改变原始对象。下面是一个使用这个模块的简单例子:

[3] pry(main)> m = 'hi'
=> "hi"
[4] pry(main)> m.extend(Chainable).as { |m| m << '!' }.as { |m| m+'?'}
=> "hi!?"
[5] pry(main)> m
=> "hi"

如果有人发现此代码有任何问题,请告诉我!希望这可以帮助。

于 2015-09-24T14:37:52.097 回答