Verbose Logging

software development with some really amazing hair

T + G I F R

Simple Ruby Pipes

· · Posted in Programming
Tagged with

Here's something I cooked up this evening. Nothing too epic, but it's a neat illustration of metaprogramming with ruby.

#!/usr/bin/env ruby
class Symbol
def pipe(method)
proc { |array| array.send(method) { |elem| elem.send(self) } }
end
def detect
pipe(:detect)
end
def select
pipe(:select)
end
alias :filter :select
def reject
pipe(:reject)
end
end
class Array
alias :old_pipe :|
def |(other)
case other
when Symbol
self.map { |elem| elem.send(other) }
when Proc
other.call(self)
else
old_pipe(other)
end
end
end
a = [' foo ', ' bar ', ' ', ' baz ']
puts a.inspect # => [" foo ", " bar ", " ", " baz "]
puts (a | :strip).inspect # => ["foo", "bar", "", "baz"]
puts (a | :strip | :upcase).inspect # => ["FOO", "BAR", "", "BAZ"]
puts (a | :strip | :upcase | :empty?.reject).inspect # => ["FOO", "BAR", "BAZ"]
puts (a | :strip | :upcase | :empty?.select).inspect # => [""]
view raw pipes.rb hosted with ❤ by GitHub

Ruby allows you to reopen classes and add methods to them. You can also make a Module and include that in a class to add methods. I've added four methods to the Symbol class and overridden one method in the Array class (using alias to keep the old method around since super doesn't quite work).

Now we can pipe arrays like bash using a simple syntax! Wee!