Dynamic scoping

Allen Wirfs-Brock Allen_Wirfs-Brock at Instantiations.com
Fri Jan 31 02:25:45 UTC 2003


At 06:38 PM 1/30/2003 -0500, Anthony Hannan wrote:
>Attached is another version of my dynamic scoping and replaces the
>previous one I sent out a couple of days ago.  It now looks like:
>
>foo
>         [self bar] on: #world do: [myWorld].
>
>bar
>         thisContext outer world.

Anthony,

I've been watching the dynamic scoping threads with some interest as it 
involves a subject that I have some experience with.  Also as the inventor 
of the on:do:/ensure:/ifCurtailed: vocabulary I may feel a little 
protective about its use (or misuse).  Unfortunately, I really don't like 
your above proposal so let me try to convince you to also dislike it.

The topic at hand is dynamic "variable" scoping. Let's assume that dynamic 
scoping indeed would be useful to have in Squeak.  Let's also assume that 
dynamically scoped bindings are not intended to be a replacement for 
conventional Smalltalk global "variables"  (I know that such a replacement 
has been suggest but it doesn't appear to be part of your proposal and 
hopefully Mark Miller will finish convincing everyone that this is a bad 
idea.)  Given this assumption, we can talk about how we want this new 
feature to appear to its users (Squeak programmers).  Here are some 
principles I would apply in designing such a feature:

1)      It should be easy to explain the feature to a new or relatively 
unsophisticated Squeak programmer.
2)      A single, specific implementation technique should not be assumed 
or required.
3)      Usage should not require deep knowledge of low level system 
implementation details.
4)      Protocol vocabulary should be simple and reflect the intended usage 
model.
5)      Protocol vocabulary should not expose the user to the vocabulary of 
the low level system implementation.
6)      Protocol vocabulary should not imply or require a particular 
implementation strategy for the feature.
7)      A distinct feature should use a distinct vocabulary that is 
different from that of other, unrelated features.
8)      Don't design in "bugs waiting to happen"
9)      Put the most important things first.

So let's first look at your example for establishing a dynamically scoped 
binding:
>foo
>         [self bar] on: #world do: [myWorld].
  and examine it in light of these principles:

1) You are going to have to explain that while it looks just like 
establishing an exception handler it actually means something else.
2) At the very least you require a change to the implementation of #on:do:.
3) You're maybe ok on this one but wait until we get to bar!
4)The on:do: vocabulary suggests nothing about dynamic binding, it's 
scoping, etc.
5) see 3 above
6) Some sort of strong connection to exception handling is clearly implied.
7) It looks like an exception handler! If you see:
          [ ] on: a do: b
   (where a and b are variables) there is no clue to tell the reader the 
programmer's intent.
8) The goal is to bind a particular value over some scope.  However, you 
aren't binding a value, you are binding a lexically scoped "function" that 
computes a potentially new value each time the binding is accessed.  Pitty 
the poor programmer who doesn't realize that "myWorld" is assigned to 
somewhere within a "bar"
9) Imagine if the receiver is a several line block.  A reader won't see 
that a new binding has been established until having read the entire 
block.  In this case, I think the establishment of the scoped binding is 
the most important aspect of the feature. (I know, exception handling 
#on:do seems to violate this but I would argue that when establishing an 
exception context that the block to be evaluated is most important thing to 
the user and should come first while the exception and its handler are 
"exceptional" and hence should come second.

Now for:
>bar
>         thisContext outer world.

1) I wouldn't even know where to start!!!
2) Must be implemented using contexts.  Must use #messageNotUnderstood: in 
its implementation.
3) Anything that references thisContext fails this criteria
4) It doesn't say anything about dynamic scoping.  It's just a sequence of 
messages  that imply nothing.
5) see 3 above
6) see 2
7) It really doesn't have a vocabulary.  It's an idiomatic usage of this 
context outer and undefined messages
8) What if the name you want to find is already the name of a method in 
whatever outer returns!
9) thisContext??

Hopefully, by now you are convinced.  I think that some of the other ideas 
for dynamic variable "syntax" probably come closer to my principles 
(remember I'm only talking about the surface "syntax" of the proposals, I 
reserve judgment about some of the implementation ideas).  However, I can't 
resist throwing out some other possibilities:

foo
         Binding for:#world is: myWorld during: [self bar]

bar
         Binding for: #world

Programmers with a Scheme background might perfer:
foo
         (Fluid named: #world value: myWorld)
                 do: [self bar]   "or just #named:value:do"

bar
         Fluid named: world

If you want to get radical with a core system class consider:
foo
         #world is: myWorld during: [self bar]
bar
         #world is

etc., etc...

Anthony, keep up the good work but remember that language design and 
language implementation are different tasks.  When you are designing a new 
language feature first think like a user and then validate it as an 
implementor.

Alle_Wirfs-Brock at instantiations.com











More information about the Squeak-dev mailing list