Clojure’s interpose and interleave in Ruby
These days I’m reading a great book titled “Seven Languages in Seven Weeks” by Bruce Tate, currently I’m on Clojure, and I am really surprised how easy it is to follow, knowing Ruby beforehand.
In chapter on lazy evaluation, I noticed couple of methods that didn’t have their exact counterparts in Ruby, and I was curious how hard would it be to implement them. So, there they are.
interpose works similarly to Ruby’s join, just more generic: its result is not String, but lazy sequence of elements from the starting sequence, with object given as argument inserted in between each two.
Here it is, implemented in Ruby:
module Enumerable
def interpose obj
Enumerator.new do |yielder|
self.each_with_index do |elem, i|
yielder.yield obj unless i == 0
yielder.yield elem
end
end
end
end
p [:lather, :rinse, :repeat].cycle.interpose(:and).take(5)
#=> [:lather, :and, :rinse, :and, :repeat]
interleave works similarly to Ruby’s zip, but this one also works on lazy sequences, not Arrays, as in Ruby, meaning that you can apply it to indefinite sequences as well. Here it is in Ruby:
module Enumerable
def interleave another
this = self.to_enum
another = another.to_enum
Enumerator.new do |yielder|
loop do
yielder.yield this.next
yielder.yield another.next
end
end
end
end
p (0...2).cycle.interleave((0...3).cycle).take(20)
#=> [0, 0, 1, 1, 0, 2, 1, 0, 0, 1, 1, 2, 0, 0, 1, 1, 0, 2, 1, 0]
Both examples are taken directly from Bruce Tate’s book.