Schrödinger's Duck

Posted by Rick DeNatale Thu, 21 Sep 2006 15:27:00 GMT

Once again there’s been a recent furore about the meaning of Ducktyping on the ruby-lang mailing list.

A nice young man from Sweden, by the name of Ola Bini, announced “ductator” a ruby-gem which allows type validation of ruby variables. Now I think that Ola is young based on the photo on his blog site, and I know that he’s nice because only nice people inhabit ruby-lang.

The real question is just what kind of a type system ductator represents. I’ve taken a brief look at it and it seems to allow one to describe, via a hash, a list of rules which are applied to a variable’s value at run-time. These rules are things like a list of methods the value must have, a class which the value must be an instance of, or an instance of a subclass of etc.

The Cat is Dead, Long Live the Cat

In 1935 Erwin Schrödinger, proposed his famous thought experiment, in which a cat, a a radioactive atomic nucleus, and a cannister of poison gas rigged ot open if the nucleus decayedare placed in a sealed box. The half-life of the neucleus is such that there is a probability of 1/2 of the nucleus decaying within one hour. Because quantum mechanics states that until a decay is observed, the nucleus really exists as a superposition of decayed and undecayed states, that the cat is both dead and alive until the box is open and the observation is made.

Schrödinger’s experiment is really a dramatized version of a similar thought experiment previously published in a paper co-written by Einstein. Although Einstein intended it as a refutation of the probabilistic nature of quantum mechanics, the stochastic basis of quantum mechanics has held up over the ensuing seven decades, and such paradoxes have held up.

My point here is that, in a sense, the kind of type checker represented by ducktator. It attempts to observe certain aspects of an object, and in so doing, has a good chance of killing the duck.

Besides the questions of what duck-typing is or is not, such a set of checks fails under many common usages in ruby.

False Negatives

Relying on responds_to? fails under commonly used Ruby metaprogramming techniques.

It’s very common these days to use method_missing to provide pseudo-methods, or to create methods on the fly. ActiveRecord and other RubyOnRails componentry makes extensive use of this technique.

The problem is, of course, that an instance of a class which uses these techniques effectively gives an invalid response to responds_to?, or may reply false, until the missing method is invoked, creating the method.

Poking around a bit, I notice that some of the standard library classes, and others liek ActiveRecord, go to some lengths to make responds_to? track with phantom methods implemented via :method_missing, although fixing other reflection methods like :methods and the class method :instance_methods doesn’t seem to be commonly done. While this is good, it can greatly increase the expense of :responds_to?. ActiveRecord::Base, aliases :responds_to? as responds_to_without_attributes? before redefining :responds_to? for this reason.

In the case of Drb::DrbObject, which is used as the proxy object in Distributed Ruby, handling :respond_to? on behalf of a remote object, requires marshalling a :respond_to? message to the remote object, sending the marshalled message, then reading and unmarshalling the reply. This makes sending :respond_to? to a remote object much more expensive.

And irony of ironies, ductator uses :method_missing to supply phantom methods in it’s implementation, without implementing a compensating :respond_to?!

False Positives

Even if one accepts the philosopy posited by ductator, using it can get tricky. For example, one might check to see if an object responds_to?(:each), but exactly what :each does and how it interacts with it’s block argument, depends on the class itself. For example, most enumerables yield a single value to the block in :each, but Hash yields both a key and a value. The block can be written to accomodate this, but it doesn’t have to be. It’s not clear to me how to either express or check the type of such block arguments. I don’t see a mechanism in ductator even to check the arity of a proc, and although this could be added, it’s not really sufficient since it doesn’t express the types required of block arguments.

What’s the Value?

Some folks might find something like ductator to their taste, since it give the impression of making Ruby more like Java or C++. The problem is that in so doing, it makes Ruby less like Ruby. This kind of type checking seems to be an expensive add-on to the real checking which happens during program execution. The fact that everything is an object in ruby means that the really nasty errors in a language like C when you use an integer as a pointer don’t happen. It seems to me that the best that something like ductator can do is to make a more ‘meaningful’ error description when something goes wrong, but doing that correctly is harder than it first appears, and in most cases could be accomplished more efficiently by catching errors with rescue clauses and changing the error reporting, after the fact, which puts the cost of the error on the offender rather than taxing everyone with run-time pre-flight tests.

Wrapping up for now

The French word for “duck” is “canard.”

In computer jargon, the word “canard” means a “mistaken and confused belief”. In my humble opinion, the view of duck typing taken by ducktator and its ilk is in this sense really “canard” typing.

Le canard est mort, vive long le canard!

Or translated into English:

The canard is dead, long live the duck!

Posted in  | Tags ,  | 4 comments | no trackbacks

Comments

  1. Ryan Daigle said 1 day later:
    Come for ruby talk - get quantum mechanics lesson. Loved it.
  2. Robert Dober said 2 days later:
    I will try to spell everything right, *this* time. Nice reading, I did not know that respond_to? (never forget Matz is not a native speaker either) was so frequently abused. I will avoid any discussion about ducktyping, early checking or dynamic type checking, but in any case: Exception handling can ( I daresay, shall ) be used. Excellent travail mon ami. Robert
  3. Robin said 3 days later:
    Isn't it *Erwin* Schrödinger?
  4. Rick DeNatale said 5 days later:
    Robin, right you are! I guess that's what I get for using typo as a blog engine!

Trackbacks

Use the following link to trackback from your own site:
http://talklikeaduck.denhaven2.com/articles/trackback/32

Comments are disabled