On 30 Sep 2010, at 16:27, Loren Segal wrote:
> We seem to be talking about two very different things here. The fact =
that Ruby takes code blocks as parameters doesn't change the fact that =
you can still insert type annotations for an existing method. "Anaemic" =
is one thing, but we're not talking about a feature that will be useful =
in *all* cases, simply a feature that will have high impact on the =
majority of existing code. While there are many tricks in Ruby, and many =
frameworks use these tricks in limited areas, the majority of Ruby code =
still tends to be standard every day non-metaprogrammed Ruby, which =
could easily benefit from these annotations.
>=20
>>> You can replace the method itself (alias_method), but because type =
annotations would be attached to the methods themselves, the type =
information would be replaced too.
>> As I mentioned in my previous reply to Martin, the compilation =
boundary you are tacitly assuming exists is in fact no such thing. You =
therefore have to consider that any use of module_eval, class_eval, eval =
or class opening may result in type annotations coming into existence at =
an arbitrary point during program execution and likewise being =
discarded.
>=20
> I'm not making any assumption about compilation boundaries, and I very =
much know that Ruby is known for making run-time changes to program =
structures. Fortunately, *_eval has no effect on whether or not type =
information is provided. Again, type annotations are not only meant for =
"compile-time", and I never made that claim. I can easily consider that =
annotations would come into existence at an arbitrary point during =
program execution. That fact has no bearing on the benefits. I ask you: =
what's wrong with that?

It appears that this proposal would require the runtime to add a new =
layer to for checking the posited nominal type annotations which =
perforce could be invoked at any point during program execution and =
indeed possibly repeatedly during the lifetime of that execution. =
Bearing in mind that nominal type is not the primary determinant of =
object validity or code correctness in Ruby, and that there are already =
existing methods for confirming nominal type identity (more of that =
anon) it's not at all clear that type annotations on this model would be =
a noticeable improvement.

>>> Therefore, you can consider any type annotations to a method =
declaration to be something of a "contract" for using the method. Of =
course you can misuse types here (specify something too limiting, or =
something completely wrong), but it wouldn't be fair to consider the =
misused cases first. Do you have any examples of where meta-programming =
would "repurpose" an object such that existing type information would be =
completely invalid?
>> For some classic examples I recommend studying various of _why?'s =
projects, or at least pondering some of the more unusual tricks in his =
(Poignant) Guide which is an excellent exploration of how to really use =
Ruby's type system to your advantage. On a more mundane level, tricks =
like this exist inside various versions of Rails and many other popular =
projects.
>>=20
>=20
> Do you have a specific example? It's easy to say "they're out there, =
just look". Again, I should point out that I'm aware what things can be =
done with Ruby at run-time, but that is not the purpose of this =
discussion. I'll ask again: what Ruby idiom or meta-programming could be =
used in order to make an existing (and still existing) type annotation =
no longer useful for: 1) documentation, 2) optional run-time type =
checking, 3) method overloading, 4) run-time compiler optimization?

Unfortunately runtime mutability is very much at the core of this =
discussion as it carries the implicit assumption that the annotations =
must be checked dynamically as the state of Ruby's type-space changes. =
Not only because the method possessing the annotation might change, but =
because the type to which the annotation refers may itself change or =
disappear. To some extent it's similar to the difference between =
Classical mechanics, where light is either a wave or a particle and =
behaves according to certain macroscopic expectations, contrasted with =
Quantum mechanics where you look beneath the surface and realise that =
such distinctions are really poor approximations of a much richer and =
yet less deterministic reality.

With Ruby you're free to play with the raw type-space in its full glory, =
and that introduces certain fundamental limitations on just how much you =
can definitively say about that type-space at any given point in time. =
Annotations might well be useful markers in some circumstances, but just =
as in QM an observation causes the quantum world to collapse into =
classical reality so with Ruby you run the risk of collapsing back into =
a static nominal type system with all that entails.

I appreciate this is a very high-level analysis so I'll bring this down =
to earth.

In essence every Ruby object is first and foremost an instance of its =
own singleton class backed up by a superposition of classes, =
meta-classes and modules from which that singleton class draws its =
specific character. Any of these elements might be reloaded or redefined =
at any time using appropriate hooks in the runtime. Duck-typing allows =
us to conveniently overlook this fact by focusing on what usually =
matters to us when we're reasoning about our code: whether or not an =
object responds to the messages we're interested in sending it, and how =
to elegantly recover when in fact that message is inappropriate - either =
through runtime exception handling or by capturing the message with =
method_missing and performing some fallback operation.

In this model runtime type checking and method overloading can already =
be performed with Object::kind_of?, but the type guarantee is localised =
to a particular expression in the code and subsequent expressions may =
change the nominal type of the object in question. As such it's a =
brittle idiom because it captures only a snapshot of the full system =
state.

It's possible that Ruby's semantics could be expanded to use kind_of? =
individually or in combination as a guard expression, freezing a given =
object for the duration of the expression so that it becomes type =
invariant and allowing optimised code to be produced. The same pattern =
could also likely be used with responds_to? to optimise method calls. =
Both of these changes would seem more in keeping with the Ruby Way than =
explicit type annotations as proposed, although I'd be loathe to see =
either implemented without considerable proof that they would indeed =
benefit Ruby and not lead to the brittleness and fragility so often =
associated with nominal typing. Otherwise Ruby would become a less =
expressive language to the detriment of all of us.


Ellie

Eleanor McHugh
Games With Brains
http://feyeleanor.tel
----
raise ArgumentError unless @reality.responds_to? :reason=