Is there a `pipe` equivalent in ruby?

前端 未结 3 1825
甜味超标
甜味超标 2020-12-11 17:12

Occasionally when writing Ruby I find myself wanting a pipe method, similar to tap but returning the result of calling the block with

相关标签:
3条回答
  • 2020-12-11 17:54

    Ruby 2.5 introduced Object.yield_self which is exactly the pipe operator you're using: it receives a block, passes self as the first argument to it and returns the result of evaluating the block.

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

    Example usage:

    "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
    0 讨论(0)
  • 2020-12-11 17:55

    Here's the the technique I use to chain objects. It's pretty much exactly as above except I don't reopen the Object class. Instead, I create a Module which I will use to extend whatever object instance I'm working with. See below:

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

    I've defined this method to prohibit mutative methods from altering the original object. Below is a trivial example of using this module:

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

    If anybody sees anything wrong with this code, please let me know! Hope this helps.

    0 讨论(0)
  • 2020-12-11 18:02

    This abstraction doesn't exist in the core. I usually call it as, it's short and declarative:

    class Object
      def as
        yield(self)
      end
    end
    
    "3".to_i.as { |x| x*x } #=> 9
    

    Raganwald usually mentions that abstraction in his posts, he calls it into.

    So, summing it up, some names: pipe, as, into, peg, thru.

    0 讨论(0)
提交回复
热议问题