On Wed, 8 Dec 2004 03:13:07 +0900, Nicholas Van Weerdenburg <vanweerd / gmail.com> wrote: > On Wed, 8 Dec 2004 01:06:53 +0900, Austin Ziegler > <halostatue / gmail.com> wrote: [snip] >> The "need" for immutability is very, erm, mutable and can be >> worked around with various design decisions. > I agree- good interface design effectively creates immutable > classes if desired. But that can be an issue because the object > may only desire immutability later in its lifecycle, or too > certain clients. I'm still not convinced, and I think that the problem that I'm seeing is that you're assuming that an object's desire for immutability is a necessary thing. I don't see such. What I'm trying to draw out from you is a discussion of the design where you feel that you need this feature to help me understand why this fundamental change to the language would be a good one (and, by extension, help others understand that as well). Alternatively, in such a discussion, we actually figure out what you want to do with Ruby and how not to modify Ruby so fundamentally by making your design more "Ruby"-like. I'm not claiming to be "all that" as a Ruby developer, but I think that I've managed to get a fair idea of the feel of good Ruby design over the last two and a half years :) > Also, good design is an ideal case. In a large project, things can > become ugly and to be able to enforce a high-degree of control via > immutable objects can be beneficial, IMHO. Good design requires > good contracts to enforce it. Again, I don't necessarily agree. I think that's an absolute requirement in Java, but I think that Ruby doesn't really require that. > There are three things that make up an immutable object so far in > our discussion: > 1. frozen objects -this could also be done with good interface > design for certain cases. other alternatives to freeze would be > useful to know- wrap/delegate, undeffing, etc. > 2. frozen attributes (assignmentFreeze) -mostly appplies to > inheritence, so private instance variables would help here. > 3. frozen value objects (referred to objects of a certain type) > -not really discussed yet, but seems important as without it, > freeze is only slushy. I and others pointed out a fundamental problem with #3 and Ruby -- how do you define type? If you're thinking in terms of Java types, that's definitely the wrong way to think about type in Ruby. An object's class is not necessarily it's type in Ruby. (See my discussion at the end of this email about StrictVar.) > It's hard to describe the benefits of immutables in a short > example, but I think it's similar in nature to global variables- > with mutables, edits can be done in many places, leading to bugs > as well as maintenance issues. Again, I'm not sure that this is a guaranteed situation in Ruby. Look at Rails -- trying to implement an immutable in a Rails application would probably break the application. I developed a bug tracking application in Perl (and will be reimplementing it in Ruby at some point) and have never had a need for an immutable. In the C++ and PL/SQL billing and CRM application I worked on a few years back, I don't recall any immutable objects, or any problems because we didn't have them. [snip] > If an object should protect it's invariant nature, then it would > be nice for ruby to provide some capability for immutable value > objects- maybe something like: > # returns defensive copies > value_reader :name, :location, :value Not hard: class << Module def value_reader(*symbols) symbols.each do |sym| self.define_method(sym) do || self.instance_variable_get("@{#sym}").dup end end end end Untested air code :) You could implement it with Marshal.load(Marshal.dump(variable-value)) for a deep clone. I'm not sure that the distinction between value objects and reference objects is needed -- the distinction isn't present in Ruby. (Well, it is, but for the most part, it's transparent to you, the programmer.) >> You assert the value of immutability, but you haven't actually >> demonstrated the value. I'm really not trying to be difficult >> here, but what sort of immutability to you mean in Java -- and >> why do you then need it in Ruby? I find that most of the time >> when people say that they want particular features in Ruby they >> do so because they're not *thinking* in Ruby, but in other >> languages that they have to deal with on a daily basis to pay the >> bills. I know I do it, from time to time, with C++ now that I'm >> making my money from that. > I'm still learning to "think" in Ruby for sure, but the essence of > the need comes from non-trivial systems without a perfect design. Again, I'm not really sure that this is true for Ruby. I think that the essence of the need comes from heavyweight Java and EJB designs, not dynamic languages. As Morpheus said in _The Matrix_, "Free your mind." > Removing singletons and making certain domain objects immutable is > somewhat like putting aspects of the "Law of Demeter" into place. > http://c2.com/cgi/wiki?LawOfDemeter I'm willing to engage in a longer discussion on the design you're seeing for this -- because I think that there are probably other ways to approach this in a language like Ruby without requiring changes to the core language that would, IMO, be detrimental. > Another way of thinking about is in terms of object lifecycle- if > it becomes immutable at some point, there is less to worry about. > In a large system, I would freeze and object just prior to > releasing into the "wild"- e.g. outside the boundaries of my > subsystem. Why? All I have to do to unfreeze your object is dup it. Why limit what people who may write on top of your classes can do? Certainly, don't necessarily trust what they provide back to you without verification, but I don't see any reason to actually do this. >>> And is there anyway to may attributes private so that subclasses >>> can't see them? IIRC, this is possible feature of Rite. This >>> would remove some of the need, since immutability is enforced by >>> invisibility. >> Um. What do you mean by "attributes"? If you mean that which is >> generated by attr_accessor, then: >> >> class A >> attr_accessor :foo >> private :foo, :foo= >> end # => A >> class B < A; end # => nil >> B.new.foo = :bar >> # => NoMethodError: private method `foo=' called for >> # #<B:0x2b52c38> > I meant the case where the instance variable @foo is accessed in > side the class B. Right, but Matz has suggested that B should never access @foo directly, but should try to do so through the foo method. I don't see a reason to make @foo itself "private" in the sense that Java and C++ have private variables. >> If you mean instance variables, no, and that wouldn't work anyway >> -- it would simply be a source of errors. >> class A >> attr_accessor :foo >> private_var :@foo >> end > private_var is a concept? Yes. >> I don't know what itsme really wants, because I think that the >> idea of making variable bindings -- instance or otherwise -- >> frozen is a bad idea. Freezing an object freezes that object's >> state -- which includes assignment to instance variables, >> certainly, but also inclues adding singleton methods, modifying >> the singleton object, extending the object, etc. > I think private variables would alleviate much of the need. I don't think so, actually. I would like to see, as I said, a @<foo> form (it may be different) so that you have privately decorated instance variables generated by the Ruby parser so that there's no collision from modules to classes, but ... that's a minor desire. In earlier messages, you mentioned a "type freeze" for a variable. There's no reason you can't do that indirectly: class StrictVar def initialize(value, &block) @value = value @cond = block end def cond=(cond) if @cond raise ArgumentError else @cond = cond end end attr_accessor :value def value=(val) if @cond and @cond.cal(val) @value = val else raise TypeError end end end That, of course, isn't a complete implementation of the delegate that you'd want to do for that, but you could do an arbitrary block: a = StrictVar.new("a") { |x| x.kind_of?(String) } Now, the object referred to by StrictVar will only be able to be Strings. -austin -- Austin Ziegler * halostatue / gmail.com * Alternate: austin / halostatue.ca