I previously lamented this code:
def parenthesized_list(array)
list = "("
first = false
array.each do |element|
if (first)
list += ","
else
first = true
end
list += yield element
end
list + ")"
end
I still haven’t found a magic bullet in Enumerable or Array which will let me dramatically shrink it. But I have at least teased out some of the components; this is what I’m using for now:
def parenthesized_list(array)
array.process_and_interpose("(", ",", ")") { |element| yield element }
end
class Array
def process_and_interpose(initial, middle, last)
inject_with_index(initial) do |memo, element, i|
memo + yield(element) + (i != length - 1 ? middle : last)
end
end
end
module Enumerable
def inject_with_index(initial)
result = initial
each_with_index { |element, i| result = yield(result, element, i) }
result
end
end
inject_with_index doesn’t seem like a crazy idea; process_and_interpose is a bit specialized, but that’s fine.
Is there some way I can shrink the implementation of inject_with_index? I get the feeling that there’s some sort of generalization staring at me there, but I can’t quite figure it out. If I’m just shrinking code, I could keep on storing in initial instead of introducing a new variable result; I’d want to rename the variable, though. Maybe this?
module Enumerable
def inject_with_index(memo)
each_with_index { |element, i| memo = yield(memo, element, i) }
memo
end
end
I don’t think I like that so much, though: naming the (non-block) argument memo instead of initial it makes it harder to figure out how it gets used. So I kind of prefer calling the argument initial at the start, and then renaming it to result in the body to reflect the implementation.
And of course parenthesized_list is funny in that it just wants to pass along the block that it’s been given, but has to create a new block to do that. That, I think, reflects one of Ruby’s warts: there’s this weird block/procedure distinction that doesn’t, as far as I can tell, buy you much. It’s nice to be able to write blocks on the fly, but why not require functions taking one to make the block argument explicit and get rid of yield? I’m not sure of all the implications, but I don’t think that Ruby’s current choice is the best.
Post Revisions:
There are no revisions for this post.

Posts
[…] malvasia bianca « parenthesized_list revisited […]
6/24/2007 @ 8:33 pm
[…] I was missing Array.join: […]
6/30/2007 @ 4:35 pm