On Sep 6, 1:27   
> Sorry, somehow I seem to have forgotten to send this earlier.
>
> 2008/9/5 Trans <transf... / gmail.com>:
>
>
>
>
>
> > On Sep 5, 7:54 am, "Robert Klemme" <shortcut... / googlemail.com> wrote:
> >> Hi,
>
> >> I just had a use case where I wanted to have several counters and not
> >> store them in a Hash because of the nicer syntax of OpenStruct.
> >> Currently, the code has to do
>
> >> counters = OpenStruct.new
> >> ...
> >> counters.foo ||= 0
> >> counters.foo += 1
>
> >> For obvious reasons I'd like to get rid of the initialization.
>
> >> The suggestion would be to do this: if the argument to
> >> OpenStruct#initialize is not a Hash use it as default value which is
> >> returned for undefined properties. As far as I can see this won't
> >> break existing code since the default is nil.   > >> could do
>
> >> counters = OpenStruct.new 0
> >> ...
> >> counters.foo += 1
>
> >> We could go even further and copy the Hash approach by also allowing a
> >> block which is invoked when a property is accessed for the first time.
> >>        
> >> value would be used to initialize the property.  
>
> >> data = OpenStruct.new {[]}
> >> ...
> >> data.animals << "cat" << "dog"
>
> >> or even
>
> >> data = OpenStruct.new do |sym|
> >> case sym
> >> when :animals : []
> >> when :dictionary : {}
> >> end
> >> end
>
> >> In other words: declarative lazy initialization.
>
> >> Again, existing code would not be affected.
>
> >> What do others think?
>
> > I recently submitted a patch that allowed OpenStruct to take a self
> > yielding block, e.g you could do:
>
> >    > > o.animals = []
> > o.dictionary = {}
> >  
>
> > I don't really see that much use for complex lazy initialization as
> > you suggest.
>
> I don't view it so much as complex initialization but rather
> declarative lazy initialization because it saves you the effort of
> writing all those getter methods.
>
> > Though, I can see the Hash block form being useful. Maybe
> > that would be a better use of the block. Actually, both could be
> > supported if we differentiate on the arity of the block. With two
> > args:
>
> >      >
> > Note, my patch also add #[] and #[]=, which are more important
> > changes.
>
> Yes, that's a good idea!

Glad you agree. Hell of a lot faster then send(key) and
send("#{key}=", val).

Mention it on ruby-core!

> > Robert would you like to update my patch to support the Hash block
> > notation and resubmit it?
>
> I would rather not want to have two interpretations for the block
> because this can easily lead to confusion and subtle bugs can creep in
> when accidentally having the wrong arity.

That was my first though too, but then I considered it a bit more and
think it makes enough sense. If we are asking for just the OpenStruct
object, ie. OpenStruct.new{ |o| ... } then clearly we are interested
in working with the object. If we ask for the key as well, ie.
OpenStruct.new{ |o, k| ... } then it is also clear we are instead
interested in doing something with a key. It's really not any
different in principle from other method interfaces, like using one or
two arguments with #slice.

T.