From: Ken Bloom Date: 2008-04-23T08:10:11+09:00 Subject: Re: why doesn't ruby have generics? On Sat, 19 Apr 2008 14:44:20 +0200, Robert Klemme wrote: > On 19.04.2008 14:04, Florian Gilcher wrote: >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> >> On Apr 19, 2008, at 1:45 PM, Robert Klemme wrote: >> >>> On 19.04.2008 12:06, Florian Gilcher wrote: >>>> On Apr 19, 2008, at 11:58 AM, thufir wrote: >>>>> Is it because Ruby is dynamic, or something else? >>>> Why would you bind to a type in a language that doesn't really care >>>> about types? Otherwise, it is easy to implement such functionality - >>>> just build a new kind of array that has to be constructed with a >>>> class. Check for this class on insertion. I don't see the use, >>>> though. >>> That would be a type restricted Array but not a generic Array. You >>> cannot have generics in a language whose variables are typeless as >>> Arlen pointed out. >> >> Yeah, thats why I was talking about "such functionality". It would >> serve the same purpose. I was not clear enough about that. > > For practical purposes you are probably right. But strictly speaking > there is a difference: Java Generics basically are a mechanism for > automated casting. This is something else than restricting the type of > items you put into a collection. (You can sneak an Integer into a > List in Java.) > > C++ templates are a completely different story - although they "look" > pretty similar to Java's Generics. C++ templates allow for generic > programming which is something different altogether. > > In Ruby you can do neither: you cannot cast because variables are > typeless. And you cannot have generic algorithms for the same reason. > > Kind regards > > robert AFAICT, the functional difference between generics in Java and C++ are: * In C++, you can use the generically inferred type names to construct new objects of those types. Multiple versions of the generic types/ algorithms are typically compiled, for dealing with objects that have the same interface but are not involved in an inheritance relationship. So the result is kinda like duck typing, but you cannot mix objects of different types in the same container. * In Java, you can cast a List to a plain old List, and when you do so you lose all type checking. You can also cast a String[] to an Object[], in which case type checking is done at runtime. Java also allows (requires) constrained genericity e.g. List. The result is less flexible than duck typing. You also lose the C++ ability to construct new objects of the same type, tough you can work around this by using factories. (Class objects can be used in a pinch, but they're not always as flexible as you need for this task.) How does ruby measure up? Ruby has duck typing. When you look at Java 5 Generics or C++ templates from the evolution of their languages, the clear idea is that you're getting more type flexibility than you had in C or Java<=1.4, and that these languages are trying to move in the direction of duck typing. In this sense, Ruby is much better (and C++ is better at it than Java, though C++ has the disadvantage of more compile- time code-size blowup). If you're looking from the perspective of what typing rules are still enforced, C++ has the best type enforcement, followed by Java, though I suspect that Java's issues there are for backward compatibility and if that wasn't a consideration, Java's type enforcement would be very much like C++'s. Ruby would be worst at type enforcement, because Ruby is designed with the opposite philosophy. Ruby's duck typing can handle objects with similar interfaces which are not related through inheritance, because it always looks up method calls by name, and because there's no such thing as a "friend operator" as C++ has. Ruby can accomplish this aspect of C++'s template system without code blowup because it's method dispatch is very different than C++'s. As for constructing objects of a given type in a generic algorithm, Ruby has the same limitation as Java. You need factories. Class objects can be used in a pinch, but ClassName.new may not always be enough to handle what you need. Groovy is a language for the Java VM which has a balance between Ruby's duck typing, and Java's static type system and generics. It accomplishes this by checking everything at runtime. It may not be a bad type system. Most of my complaints about the language revolve around their decision to conflate the semantics of Ruby's Hash and OpenStruct on a single class fundemental class (java.util.Map) so that there's no way around the ambiguity. --Ken -- Ken (Chanoch) Bloom. PhD candidate. Linguistic Cognition Laboratory. Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/