From: Nikolai Weibull Date: 2005-08-07T23:22:02+09:00 Subject: Re: Adding yet another Array.new form Robert Klemme wrote: > Nikolai Weibull wrote: > > How about adding a fifth way of constructing new arrays?: > > > > Array.new{|array| block } > > > > Here, array is the newly created array, and the block will initialize > > it as it sees fit, e.g, > > > > ary = Array.new{ |ary| 5.times{ |i| ary << i } }, > > > > which is a stupid way of doing it (Array.new(5){ |i| i } would do), > > but it shows the idea. I often find myself writing methods that fit > > the following template: > > > > def a > > ary = [] > > .. construct ary by adding elements to it ... > > ary > > end > But *what* are the initializations you cannot do nicely ATM? Note, > that there are also forms that make use of map and inject that can be > quite concise... Huh? Array#map and Array#inject operate on an array to produce another array or value. What I'm suggesting is a way to set up the items of an array in a nice way. (Actually, as other people have pointed out on this thread, this isn't necessary limited to arrays, but I'd say it's most applicable to the initialization of collections.) Consider the following example from my ruby-lisp format rewrite: def parse_modifiers returning modifiers = [] do until @format.eof? if (c = @format.getc) == ?: or c == ?@ if modifiers.include? c raise FormatError.new(@format.pos, "duplicate #{c.chr} modifier") end modifiers << c else @format.ungetc(c) break end end end end Without using returning, that would be def parse_modifiers modifiers = [] until @format.eof? if (c = @format.getc) == ?: or c == ?@ if modifiers.include? c raise FormatError.new(@format.pos, "duplicate #{c.chr} modifier") end modifiers << c else @format.ungetc(c) break end end modifiers end I would like to be able to write it as def parse_modifiers Array.new do |modifiers| until @format.eof? if (c = @format.getc) == ?: or c == ?@ if modifiers.include? c raise FormatError.new(@format.pos, "duplicate #{c.chr} modifier") end modifiers << c else @format.ungetc(c) break end end end end I feel that this makes it clear that parse_modifiers returns a new array and then the block passed to Array.new sets it up as appropriate. There's already support for passing a block to initialize an array, but that can only be done in the following manner: Array.new(5){ |i| i } # => [0, 1, 2, 3, 4] or Array.new(5){ |i| i * 2 } # => [0, 2, 4, 6, 8] Sure, the format I'm suggesting is perhaps limited in applicability, but how often do you do Array.new(size){ |index| ... }? I have four methods in one class whose bodies are a big returning, like parse_modifiers above, that sets up an array and then returns it, nikolai -- Nikolai Weibull: now available free of charge at http://bitwi.se/! Born in Chicago, IL USA; currently residing in Gothenburg, Sweden. main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}