From: dblack@... Date: 2003-11-06T21:57:15+09:00 Subject: Re: Managing metadata about attribute types Hi -- On Thu, 6 Nov 2003, Ryan Pavlik wrote: > On Thu, 6 Nov 2003 12:45:39 +0900 > dblack@wobblini.net wrote: > > > > I believe that's by design; as I understand it, the StrongTyping > > module performs parameter gatekeeping based exclusively on the > > class/module ancestry of an object (the namespaces to which it > > belongs, as Rich and Chad were discussing), not on what the object > > actually can do. This means, as you say, that objects which might fit > > the bill may not get through, if their class/module ancestry is wrong, > > and also that objects which do not fit the bill can get through -- for > > example: > > > This is the fundamental philosophical disagreement, or > miscommunication, or what have you. If an object fits the bill, and > its class/ancestry is wrong, then there is a error in design. > It should not be the case that this happens, or you have found an > error in your code. At this point you're waging a battle directly against the design of Ruby. Ruby allows you to extend objects at runtime; to decide that this is sloppy or wrong or a second-rate programming technique is entirely arbitrary. When you check whether or not an object's response to #is_a? includes an element you've specified, that's the one and only thing you're checking. It's not as if Ruby somehow pulls up its socks and straightens its tie and says "Better stop this dynamic stuff!" when it sees a call to #is_a? It doesn't; it remains dynamic, and the programming techniques required to ascertain the interface of an object do not change. (Besides, its socks and tie were just fine to start with :-) > I realize not all of Ruby is documented in this manner; that's a > simple matter to change. A few smaller modules would solve this; for > instance, Set, HashedSet, IndexedSet, etc. Array would be an > IndexedSet; modules such as CGI would include HashedSet. Then you > could ask for the simple behavioral pattern you desire, and know that > you have it. You would further be assured that this #[] means what > you want it to. I think I must be not getting something here; it sounds like you're suggesting that every possible behavior of every future object in every Ruby program be anticipated by modules in the core distribution, with multi-barreled names to suit the purpose. I'm thinking that can't really be what you mean. Also, remember that you're never 100% assured that #[] or any other method means what you want it to. It's ducks all the way down :-) (http://www.the-funneled-web.com/hawking.htm) Every method call operates under the same conditions as every other. You can light a candle, dance a jig, call #is_a? twenty times... but in the end, obj#[] is whatever obj#[] is. You can't change Ruby for a few nanoseconds at a time through sheer willpower. Hence the quest to harness the dynamism, rather than wishfully think that it comes and goes. > This isn't really any different than duck typing, except you're just > making sure that it really does quack, it doesn't just have a bill. Also, to reintroduce something Chad brought up: this isn't just a matter of the illusory nature of the rigor of #is_a? It's also about missed opportunities. It's quite possible to write Ruby programs that mimic statically-typed languages as closely as possible, and where checking an #is_a? list almost certainly will, in practice, indirectly give you accurate information about an object's type. But that means that, in the name of some kind of imagined rigor or discipline or something, one has decided to program using a small, somewhat impoverished subset of Ruby's capabilites. One then ends up with pretty-looking (because it's Ruby :-) pseudo-statically-typed code. Mind you, as with discussions of thread safety and name clashes, a lot of the possible weakness of #is_a?-checking pertain to what would happen if little gremlins got into your program and changed everything. In practice, if you decide to treat Ruby classes as immutable and Ruby objects as wannabe statically-typed, you will probably do OK (though your code may lack scaleability). But it's important to remember that, in doing this, you're not dealing *directly* with the types of objects. In the end, everyone has to do what they think best. I'm more interested in an object's type than its response to #is_a?, so I tend to feel comfortable with extending objects dynamically and putting them in situations where they can do their thing. If you spot (real) errors in the design of any of my programs, please let me know :-) David -- David Alan Black home: dblack@wobblini.net # New email address work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav