From: Niklas Frykholm Date: 2001-08-17T00:30:05+09:00 Subject: [ruby-talk:19903] Re: Why not?: Assigning to self On Thu, Aug 16, 2001 at 11:17:44PM +0900, Piers Cawley wrote: > Once again, I point at my 'state machine' example as an instance where > 'becoming' could be useful. The 'square'/'rectangle' thing is, as you > point out, silly. My 2c. I think #become is harmful when it changes the interface of an object. The purpose of #become is to change an object's behavior without having to manually change all references to it. But if the interace of the object changes, we will still have to do some sort of manual update to make sure that everywhere a reference to the object is used, we are aware of its new interface. So nothing is really gained. At the same time, a lot is lost. Since objects can change interface "under our feet" it becomes harder to read programs. A #become that doesn't change the interface of the object, but only the implementation, could be considered reasonably safe. Such a #become would, I think, be OK. But in Ruby and other "loose" languages, it is often hard to say what the interface of an object is. Often it is the *documentation* that defines which methods belong to the interface and which are "internal". It is hard to see how a check that the interfaces are the same could be done in Ruby. Then there is the question of whether the langauge should try to enforce a good coding style, or allow everything and let the users care about shooting themselves in the foot. Should we allow #become even if we cannot restrict it to "safe" cases? Then of course, there is the implementation issue. How much work would it be to implement #become, and is that time perhaps better spent on developing other parts of ruby? There aren't that many programs that can make good use of #become (most people have a hard time coming up with good examples) and everything that can be done with #become can be done in other ways, without too much of a hassle -- either by returning new objects (if there are not multiple references to the object) or by implementing a delegator mechanism: (Example 1 -- returning new objects) class State1 def transition(data) ... return State2.new() end end @state = State1.new() @state = @state.transition(data1) @state = @state.transition(data2) ... (Example 2 -- with delegator) class StateMachine def initialize() @state = State1.new() end def transition(data) @state = @state.transition(data) end end @state = StateMachine.new() @state.transition(data1) @state.transition(data2) ... // Niklas