From: Sean O'Dell Date: 2003-11-20T05:48:37+09:00 Subject: Re: "stereotyping" (was: Re: Strong Typing (Re: Managing metadata about attribute types) ) On Wednesday 19 November 2003 12:04 pm, Austin Ziegler wrote: > On Thu, 20 Nov 2003 02:43:31 +0900, Sean O'Dell wrote: > > > > Then don't specify a type for your arguments. Some people need > > it, some people don't. > > Who *needs* it? And why? Immediately, the classes of applications I do. I almost didn't choose Ruby because of the lack of type checking. I am primarily a C++ programmer. My guess is you're not hearing the argument of scores of C++/Java programmers because they're not here, because Ruby has zero type-checking. I mean that in all seriousness. People don't fiddle around arguing with others, generally, they just walk away. I have never said a word to anyone in the Python group about what could make Python better because there's too much wrong with it to begin with. That's my opinion of Ruby right now. I love it, but I think there are things like lack of type checking that are making people go "ah screw it" and just move on. > that *need* this are (1) RPC-based programs that are dynamically > discoverable, and therefore need cross-language inspection and (2) > interface builders (a la Visual Basic "Property Inspectors"). I > can't think of any other class of application that *needs* this sort > of meta data. I fully support being able to have this information > available, say: Then you're not thinking hard enough about it. I can't force the notion that type checking is useful if you really don't want to listen. > > Doing a respond_to? for every method you need an object to > > implement is tedious, > > Yes, it is. That's why I don't do it often. I document what the > object requires and then I expect the user to follow it. This is the > heart of duck-typing: you use the object given to you. Unless you're > doing something that requires programmatic discovery (see my notes > above), documentation is sufficient. No, documentation is not sufficient, especially since there is so much code out there that is NOT documented. It would be much easier to provide a typing mechanism that could at least report which interfaces an object provides. Developers are more likely to take advantage of that than they are to provide documentation. > > especially when developing a collection of related functions, and > > it doesn't mean that the object does what it reports to do, nor > > that it takes the parameters you expect. For example, if an object > > responds_to?(:open), what does it open? A file by name? The end > > of a socket? Which? However, if an object implements the :socket > > interface, then I know it responds_to? :open, :close:, :read, > > > > :write, :select, etc. and I know exactly what parameters to pass. > > *shrug* Whatever. Your document would read something like: > > # ios:: ios must respond to #open, #close, #read, and #write. > > > These things are important. > > In statically typed languages, sure they are. In Ruby, less so. > Consider: > > irb(main):008:0> StringIO.ancestors > => [StringIO, Enumerable, Data, Object, Kernel] > irb(main):009:0> StringIO.new.respond_to?(:select) > => true > > Oops. StringIO instances respond to #select, but they're not IO or > File objects at all. Exactly how does name checking help you here? > StringIO is a valid IO object by signature, but it's not "of IO". Well, clearly the hierarchy is not designed to report properly which interface StringIO implements, which is sort of my point. If there were an abstract IO interface, StringIO could declare itself an implementation of that interface, and methods that required that interface would then have very informative error messages for developers who passed it an non-conforming object. > > It saves a lot of code and headaches when you can just ask "does > > this object implement this interface?" > > Why do you need to ask unless you're implementing one of the cases > that I pointed out above? Look at a lot of Ruby code out there: it > *assumes* that the object provided implements the interface -- and > it documents it as such. That is my point exactly. The assumption is already there. The flexibility is already lost. You MUST provide a certain object which provides a certain interface, or you end up with a deeply embedded error, instead of an informative one pointing to your own code. > > You might not find it useful, but others definitely do. > > Mostly people new to Ruby recently from Java. Seriously. No. People experienced in both. I've programmed for Ruby for a year or so now and I still wish for some type checking now and then, when I'm digging around in someone else's code trying to figure out what parameters they expected. I don't take being called a C++ or Java programmer as an insult. I take it to mean that you don't, or haven't, programmed in either enough to see type checking as a blessing, not a curse. > > Being able to query for the signature of an interface, with some > > syntactic sugar to allow parameters to require them (optionally) > > is very much, to me, The Ruby Way; fearless and visionary. This > > should make everyone happy; people don't lose their flexibility > > and we get all the type checking anyone should need. > > Once again: ancestry/name checking is not type checking. Neither is > method checking (#respond_to?). Ruby divorces type from class, which > is something that C++ doesn't do, and Java users "sorta" get if they > think about interfaces. Terminology issue. Okay, let's call my promotion "interface declaration." That's all I advocate right now. > Anecdotally, I did some work with Ruwiki recently and Chad Fowler > created a mock object to make the Ruwiki tokenizing process think > that it was dealing with an instance of Ruwiki. That mock object has > become part of Ruwiki's object hierarchy, although not as Chad > defined it. (I abstracted the data that Chad was using into its own > object.) If I had done ancestry checking initially, Chad wouldn't > have been able to do this. Ah, ancestry checking. I see where we are crossed up in this. Let me be clearer. I only advocate "interface checking." A class is just one form of interface. A module is another, when it's mixed-in. I wholly support something like this: class MyMockRuwikiClass interface RuwikiClass end ...where RuwikiClass is the actual class that Ruwiki uses. My mixing it in as an "interface" your class is more or less saying "I implement the Ruwiki interface" but doesn't necessarily need to implement it, and certainly won't inherit anything from RuwikiClass. It's just a declaration. So if the Ruwiki tokenizer required an object that implements the RuwikiClass interface, your mock object would do just fine. > > So, although YOU might not need this, I and others do. > > Why? I'm serious. It's also a rhetorical question: why do you need > this? What about your code demands this? Is it a presumed need, or a > real need? If it's a presumed need, YAGNI. If it's a real need, why > not consider if your design and/or implementation are too fragile. A > need for static typing in Ruby is an indicator of code smell. Yes, I > have some smelly code that I haven't updated to this point. I've made a pretty good analogy in another post. > > I think this is also one of those little things that would win > > people over to Ruby. Having absolutely no solid type checking is a > > big turn-off for a lot of people, and it's what keeps them > > developing in C/C++, Java and so on. If they're contemplating > > learning a script language, this would definitely catch their eye. > > If someone wants a scripting language that requires type checking, > use PHP. Neither Perl nor Python offer type checking[1], although > Python went through this discussion a couple of years ago, and they > apparently did decide to implement an optional type system. The best > form I found from my perspective was PyIDL. Wait, you don't throw the baby out with the bath water. Ruby is infinitely superior to PHP. It doesn't have to become like PHP just to get "interface declarations." Sean O'Dell