[Grace-core] Name resolution in Grace

Lex Spoon lex at lexspoon.org
Sat Jul 6 07:11:13 PDT 2013


As a general principle, it seems hopeless to be truly modular against
changes to base classes. I would guess the same is true for dialects.
If you want to have an arms-reach relationship with another object,
then you should use delegation, not inheritance. For dialects, it
sounds just impossible to have an arms-reach relationship. You *have*
to know what language you are programming in, don't you?

For what the specific rules should be, I never know when I am just
unimaginative, but the following approach that Michael described is
used quite widely and is at least reasonable:

> Resolution means, in effect, syntactic transformation
> to have an explicit receiver, which will follow the ordinary lookup
> rules.

Admittedly, it is hard to explain which transformation is chosen
whenever there are multiple options. That much conceded, it would only
make sense to choose some other design if that other design avoids
adding something even more confusing.

There's one other design consideration I haven't seen re-raised in
this thread since the last time it went around: overriding. You want
people to be able to override and to reason about how it's going to
affect the behavior of a program.

With the static rewrite approach quoted above, you could think about
override with the slogan, "methods override methods". When you write a
method down, you *know*, statically, which other methods you are
overriding. No matter how anyone calls the original method, your
method will intercept it and get a chance to run.

With the dynamically bound self, it's less clear to me how to reason
about override. Now whether you override a method depends on whether
the caller wrote "foo()" or "outer.foo()". I'm not immediately sure
how to even get started with writing correct code under this approach.
It seems to involve the person who writes foo versus outer.foo being
aware of the distinction, so that they can make a good choice between
the two. However, I'm not sure what the caller should be thinking
about when they decide which one to write. Certainly this sounds
harder than where we started. The original motivation to allow foo()
instead of self.foo() or outer.foo() was, I would think, that the
receiver is too obvious to merit writing down. Now, we have reached a
point where if you write foo(), you aren't so much eliding obvious
boilerplate as asking for additional dynamism in the dispatch
algorithm.

All of this makes the Python and Smalltalk approach look tempting,
doesn't it? If you are calling a method, you have to write down a
receiver. It makes code longer, but it also makes code clearer.

Lex Spoon


More information about the Grace-core mailing list