Brian Candler
10/20/2004 7:48:00 PM
> Yes of course, but it's not imperative and I'm looking for an imperative
> version like the Smalltalk one.
My inclination would be to start simple:
module Enumerable
def each_with_separator(sepblk)
first = true
each do |item|
sepblk.call unless first
first = false
yield item
end
end
end
[1,2,3].each_with_separator(proc { puts "-" }) {|obj| puts obj }
But it's admittedly a bit ugly passing two blocks in this way. If you want
you can create an intermediate object which holds the separator block and
performs the iteration:
module Enumerable
def separate_by(&blk)
Separator.new(self,blk)
end
class Separator
include Enumerable # eat your own tail :-)
def initialize(thing,sepblk)
@thing = thing
@sepblk = sepblk
end
def each
first = true
@thing.each do |item|
@sepblk.call unless first
first = false
yield item
end
end
end
end
[1,2,3].separate_by { puts "-" }.each {|obj| puts obj}
I'm not sure if that's a general enough pattern for you. For example, an
Enumerable::Separator is enumerable, but you can't use 'collect' to collect
the objects and the separators.
Perhaps you want to 'yield' the separator instead?
module Enumerable
def separate_by2(separator)
Separator2.new(self,separator)
end
class Separator2
include Enumerable
def initialize(thing,separator)
@thing = thing
@separator = separator
end
def each
first = true
@thing.each do |item|
yield @separator unless first
first = false
yield item
end
end
end
end
[1,2,3].separate_by2("-").each {|obj| puts obj}
a = [1,2,3].separate_by2("-").collect {|obj| obj * 2}
#=> returns [2, "--", 4, "--", 6]
Regards,
Brian.