Hi --

On Sun, 12 Dec 2004, itsme213 wrote:

> Leaving aside freezing local variables, I am curious what you think of
> freezing controlled at the level of (the bindings of) individual Ruby
> instance variables, rather than strictly for entire objects. So I can say
> things like:
>
> class Home; def freeze ... end; end
> myHome.freeze  # cannot change door or door-knob, but can re-paint door
> myHome.door = otherDoor #=> error
> myHome.door.knob = otherKnob #=> error
> myHome.door.color = otherColor #=> OK
>
> Today's Object#freeze can be implemented using this, I believe (extended to
> deal with special cases for arrays, hashes, etc, and with the fact that
> "freeze all instance variables, ... " in Ruby might mean prohibit dynamic
> addition of new ivars). The converse is not true i.e. instance-variable
> level freeze cannot be implemented using today's Object#freeze, and the
> myHome example above is impossible to implement.

It's not impossible -- you just have to do it by other means than
Kernel#freeze.  You'd want something called attr_freeze, that did
something like:

   module AFreezer
     class FreezeError < TypeError    # or whatever
     end

     def attr_freeze(*syms)
       c = (class << self; self; end)
       syms.each do |sym|
         c.class_eval do
           define_method("#{sym}=") { raise FreezeError }
         end
       end
     end
   end

Then you could do:

   class Door
     include AFreezer
     attr_accessor :knob
     def freeze
       attr_freeze :knob
     end
   end

and so on.  (I have a longer, working example if you want to see it.)

The fact that what you want to do is freezing-related and yet isn't
going to piggyback on Kernel#freeze need not worry you in the
slightest.  Just use other techniques to achieve what you want.


David

-- 
David A. Black
dblack / wobblini.net