On Jul 31, 2009, at 09:50 , Yossef Mendelssohn wrote:

> Is it possible to modify the members of a Struct class once it's been
> created, yet retain all other behavior?
>
> An example:
>
>   Thing = Struct.new(:a, :b, :c) do
>     def some_method
>     end
>   end
>
> Is there a way to modify Thing so it behaves as if it were effectively
> created like so?
>
>   Thing = Struct.new(:a, :b, :c, :d) do
>     def some_method
>     end
>   end

I know this makes me a really bad person for doing this... but hey...  
that's what I'm here for. To take one for the team. I'm thinking of  
releasing 2 gems off of this idea. One for thaw and the other for  
struct... Hrm... there is still a problem with structs made before the  
additional member is added. I'll work that out, but I have to go to my  
workout now.

#!/usr/bin/ruby -w

require 'rubygems'
require 'inline'

class Object
   inline :C do |builder|
     builder.c "VALUE thaw() { FL_UNSET(self, FL_FREEZE); return  
self; }"
   end
end

class Struct
   inline :C do |builder|
     builder.c_singleton "
       void raw_members() {
         return rb_struct_s_members(self);
       }
     "

     builder.c_singleton '
        void set_size(long n) {
          rb_iv_set(self, "__size__", LONG2NUM(n));
        }
     ', :method_name => :size=
   end

   def self.add_member name
     self.raw_members.thaw
     self.raw_members << name

     attr_accessor name

     self.size = self.raw_members.size
   end
end

Thing = Struct.new(:a, :b, :c) do
   def some_thing
   end
end

t = Thing.new(1, 2, 3)

p [t.a, t.b, t.c]
# => [1, 2, 3]

Thing.add_member :d

t.d = 4

p [t.a, t.b, t.c, t.d]
# => [1, 2, 3, 4]