From: Joshua Ballanco Date: 2010-09-29T11:36:13+09:00 Subject: [ruby-core:32619] Re: Proposal for Optional Static Typing for Ruby On Sep 28, 2010, at 2:47 PM, Loren Segal wrote: > If you read my next example (which you conveniently left out of your quote) you can see how duck types can be expressed. You also seemed to miss my statement (which you did quote) that ducktypes *could* indeed be used. This situation, however, is not a duck-typing situation. The Server class is not meant to "act like a hash". In the example above, the run() command takes a convenience hash and constructs a server object for you (a common idiom for Ruby factory methods). I intended no offense via omission in not quoting your next example. I merely wanted to point out that testing against a specific class is not a very good paradigm to follow. I realize that an awful lot of Ruby code that you might find today includes just this sort of anti-patern, but I don't think that is a legitimate excuse. I think it's a symptom of poor design. In this specific case, I would argue that a #run method which either takes a pre-constructed object *or* parameters to construct the object for you is not very well designed. These are two different tasks. The should be handled by two different methods. I realize that this is, essentially, what you're proposing with annotating the argument types, but I wonder why you think that annotating types is better than just creating two different methods with different names? >> If you're testing your arguments against a specific class, you're "Doing it wrong". > > That's a little extreme. There are plenty of uses cases that require specific classes, or use inheritance instead of duck-typing to specify an interface. Ruby is still an object-oriented programming language, last time I checked. There's no reason not to merge the strengths of each paradigm. Object-oriented != Class-oriented If you're requiring specific classes, then you're not truly duck-typed. To be clear, I'm not attempting to make any judgement about doing things one way or the other, but I think we must be very clear about what it is that we are trying to accomplish. If you want a class-based type system, say so! But this is not the same thing as a duck type system. > This is just as messy. You're putting dispatching logic that could easily be handled by your interpreter into your business logic. Again, the solution here could still be expressed with type annotations: The reason that I didn't pick on your second example with the method requirement is that I feel like this is better handled in a formal design-by-contract syntax than as a type-signature, but that's an opinion. The more fundamental issue that we still haven't addressed is that when you say: def run(thing: #start) thing.start end You're making the implicit assumption that #start will always do what you expect. What makes Ruby difficult is not the lack of type annotations or class-based vs duck typed, it's the fact that the duck-typing is unreliable! Depending on what's going on in code you 'require', you have no idea if String#length will do what you expect, or that 'require' itself hasn't been redefined. As it is today, you could look at all the methods called on arguments inside the body of a method and automatically assign type annotations of this sort. If you wanted to do multimethod dispatch based on this information, that shouldn't be too hard to imagine how to do either and it still would not require any type annotations. As I've said before, I really don't see that type annotations add anything. If you want to argue about changes to Ruby's type system, that's a different argument all together. >> Mostly, if you find yourself doing this sort of checking too often, it's probably symptomatic of a larger issue with the structure of your code. > > Again, I would disagree. There are plenty of fairly proper codebases that use the above examples a lot. Particularly for convenience methods, which Ruby libraries have plenty of-- far more than other languages I've seen. The road to spaghetti code is paved with convenience methods...just ask a Visual Basic programmer. Cheers, Josh