"Hal Fulton" <hal9000 / hypermetrics.com> schrieb im Newsbeitrag news:411AE8D6.8060607 / hypermetrics.com... > Hello, all... > > I ran across an interesting bit of behavior, and I'm not sure I > understand why it happens. > > Here's the background. I have a SuperStruct class which I use frequently > (though I hope to find a better name for it). See the snippet on > rubyforge: http://rubyforge.org/snippet/detail.php?type=snippet&id=25 > > So. If you call SuperStruct.new, you get a class that is much like > a Struct; if you call SuperStruct.open instead, you get a class that > is more like an OpenStruct. > > That is, in the latter case, if you reference a nonexistent attribute, > it will spring into existence: > > klass = SuperStruct.open(:alpha) # Create with attr "alpha" > foo = klass.new > x = foo.beta # nil > foo.gamma = 5 # 5 > > In fact, when you referenced the getter OR the setter... then the getter > AND the setter would be defined. Make sense so far? > > But this leads to an oddity... > > foo.delta ||= 7 # gives an error! > foo.delta = foo.delta || 7 # I think this also gives an error > > I had to fix this by saying: When the getter or setter is referenced, > define ONLY that method. I don't quite like this; but oh, well. > > But puzzling out why it works this way has given me a headache. > > What do you think? I think it doesn't happen with OpenStruct: >> foo = OpenStruct.new => <OpenStruct> >> foo.alpha = nil => nil >> foo => <OpenStruct alpha=nil> >> foo.delta ||= 7 => 7 >> foo => <OpenStruct delta=7 alpha=nil> >> Personally I'd implement SuperStruct like this: require 'ostruct' class SuperStruct def self.new(*attrs) Struct.new( *attrs ).new end def self.open(*attrs) st = OpenStruct.new attrs.each {|at| st.send( "#{at}=", nil) } st end end >> x = SuperStruct.new :foo => #<struct #<Class:0x10187710> foo=nil> >> y = SuperStruct.open :foo => <OpenStruct foo=nil> But apparently you're adding more magic, so that's probably not a solution for you. Kind regards robert