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.
[…] malvasia bianca « parenthesized_list revisited […]
6/24/2007 @ 8:33 pm
[…] I was missing Array.join: […]
6/30/2007 @ 4:35 pm