LoginSignup
4

More than 5 years have passed since last update.

Rubyでshellのパイプみたいなことをやる

Last updated at Posted at 2016-04-03

RubyでもElixirの|>みたいなことをやりたかった。
RubyでShellのようなパイプ演算がしたいという動機は実は無かったのだが、Rubyで定義出来るオペレーターの都合上|を利用することになり、まぁそれってShellのパイプだよね?ということで本投稿のタイトルは「shellのパイプみたいなことをやる」としている。

こんなコードが書ける

|オペレーターはArrayFixnumで既に定義されているので、影響範囲を局所化するためにrefinementの機能を用いて実装した。
なので、使うためにはusingキーワードが必要になる。

require 'json'
require 'net/http'

using Pipe

get_url_name = URI('http://qiita.com/k-motoyan.json') \
                 | Net::HTTP.method(:get) \
                 | JSON.method(:parse) \
                 | [:fetch, 'url_name']

get_url_name.call # => 'k-motoyan'

改行したい場合は末尾に\が必要だとか、引数の必要なProcを呼ぶときは配列にしないといけないとか、処理を実行するときにはcallを呼ばないといけないとかElixirとかShellと較べてちょっとあれだけど、それっぽいことは実現出来ました。

実装

コードがDryでないとかは黙って見過ごして欲しい。

やっていることは簡単で、

  1. |の左辺に渡されたMethod(シンボルでも良い)をProc化する。
  2. 1で生成するProcの第一引数に|の右辺に渡されたオブジェクトを適用する。
  3. 2の処理を返すProcを生成する

ということをやっているだけ。

module Pipe
  def self.build_proc(proc, apply_proc, *args)
    -> { proc.to_proc.call(apply_proc.call, *args) }
  end

  refine Object do
    def |(arg)
      if arg.is_a? Array
        proc_or_method = arg.shift
        Pipe.build_proc proc_or_method, -> { self }, *arg
      else
        Pipe.build_proc arg, -> { self }
      end
    end
  end

  refine Array do
    def |(arg)
      if arg.is_a? Array
        proc_or_method = arg.shift
        Pipe.build_proc proc_or_method, -> { self }, *arg
      else
        Pipe.build_proc arg, -> { self }
      end
    end
  end

  refine Fixnum do
    def |(arg)
      if arg.is_a? Array
        proc_or_method = arg.shift
        Pipe.build_proc proc_or_method, -> { self }, *arg
      else
        Pipe.build_proc arg, -> { self }
      end
    end
  end

  refine Proc do
    def |(arg)
      if arg.is_a? Array
        proc_or_method = arg.shift
        Pipe.build_proc proc_or_method, -> { call }, *arg
      else
        Pipe.build_proc arg, -> { call }
      end
    end
  end
end

使ってみたいという奇特な人へ

勢い余ってshelike-pipeというGemにしてしまったので、gem install shelike-pipeとかやれば使えると思う。
ここで書いた内容より、多少高機能になっています。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4