From: Joshua Ballanco Date: 2010-09-29T03:42:20+09:00 Subject: [ruby-core:32608] Re: Proposal for Optional Static Typing for Ruby On Sep 28, 2010, at 3:53 AM, Martin Pilkington wrote: > I did consider structural typing and it could be a route to go down. Ultimately I'm just wanting a better way for me and others to build reliable, powerful tools for Ruby, regardless of how that is approached. I did hit a snag when considering structural typing though, which may be due to my relative inexperience with structural typing, so you might be able to help with a solution. Martin, I we risk confounding "type annotation" and "type system", and I think we need to ask what it is that we really want. Type annotations are more useful to the compiler than they are to the programmer. Even then, they are just a lazy solution to building "reliable, powerful tools" and, as James has pointed out, with a little bit of effort one can write tools that are just as powerful without type annotations. Also consider that OCaml, Haskell, and friends manage to have a stricter type system than C with almost no type annotations. C++ has copious type annotations, but I don't think anyone would claim it is easy or fun to write tools for C++. A type system is something else entirely. Type systems can be a very powerful feature for the developer, as they assist in proving the correctness of methods and conveying meaning. If you haven't I highly recommend you watch this video on the power of OCaml's type system: http://vimeo.com/14313378 (you can skip to about 45 min in where he talks about "phantom types" if you just want a really neat example of how powerful a good type system can be). The problem with attempting to apply any sort of type system to Ruby is that duck-typing is pretty much the antithesis of a strong type system. However, what would we actually be trying to achieve with a type system? If the goal is to make our code more robust, more provably correct, and to better communicate intention, I would suggest that there is an alternative way of achieving these goals without types: Design by Contract. All we would need to do is provide some means for incorporating tests into the body of our code so that preconditions, postconditions, and invariants are explicitly called out. Look at Eiffel for a good example of how this might be done. If the goal is to make code optimization easier, I would argue that types are a red-herring. Sure, you can gain some trivial amount of optimization by adding types, but why can't you infer types with Ruby currently? Here, I'd like to point to a blog post by Joe Marshall: http://funcall.blogspot.com/2009/09/first-class-environments.html . He is writing about Scheme, but the arguments he presents are just as relevant to Ruby. In particular: > "When someone suggests �first-class environments�, I assume [what] they want...is, they can grab any environment at any time, all lexical bindings are present, used or not, the bindings are live and mutable, and you can insert new, shadowing bindings...In this variation, though, the user simply cannot reason about his code. There are no abstraction barriers because any piece of code can, at any time, crack open a closure and change the meaning of any variable whatsoever. Something as simple as (lambda (x) (+ x 1)) cannot be assumed to do addition if someone injects a shadowing binding for +. Obviously you cannot compile this to an add instruction if you don't assume it will still be addition at runtime." Ruby is currently "plagued" by just such 'first-class environments'. I think that, at first, these sorts of environments seem like a very powerful and useful tool. What I have noticed over the years, though, is that the more people use Ruby, the more we are seeing the exact thing that Joe Marshall is warning about. The user simply cannot reason about his code. Likewise, even attempting to infer structural types is impossible because, as you mention, we have no way of guaranteeing that someone has not changed the meaning of "+". In short, I don't think Ruby's problem is a lack of types. I think design by contract might be a useful addition, but that does not really address the root problem. I think the real issue that needs to be addressed is that the more people abuse various features of Ruby, the harder it becomes to reason about Ruby code (for a programmer and a tool both). I'm not suggesting that we should eliminate open classes/modules, but I do think that we need to meditate long and hard about how bindings, classes, metaclasses, and methods can be made to work together in a flexible yet structured enough way that we can, again, reason about our code. Cheers, Josh