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);}