[E-Lang] Syntax change: reducing side-effects

Mark S. Miller markm@caplet.com
Sun, 11 Feb 2001 20:16:32 -0800

I've resisted saying this, but as long as we're on syntactic tangents 
besides the main point, could everyone please stop quoting in their entirety 
the message they are replying to when there's no reason?  Besides all the 
normal reasons why this is irritating, when I get one of these I usually try 
to remember to scan it to see if there are further replies buried within it. 
 Usually there are none, so sometimes I don't remember, so sometimes I'm 
sure I'm missing some carefully crafted crucial rebuttal.  Also, our email 
archiving software does not filter out this noise as seen at 
http://www.eros-os.org/pipermail/e-lang/2001-February/004438.html .

I quote the message below pointlessly in order to make the point.  Sorry, I 
just can't pass up an Epimenides moment.

At 03:38 PM Sunday 2/11/01, Marc Stiegler wrote:
>On a completely different tangent from the point you were making, are you
>proposing this multiple-closure on-a-line style for E? As in
>}   }   }   }   }
>My first reaction was shock, my second was, this really does have some
>charms, notably being able to see more actual code on the page, and in fact
>making it easier to look at and confirm that you have lined up and closed
>the whole nested structure (at least at the end of an objectMaker
>definition). The biggest disadvantage I see is that it will look alien to
>the Java programmers we are trying to lure into E by making it look "just
>like Java".
>Anyway, I haven't thought it through, so I'm asking in case you have :-)
>----- Original Message -----
>From: Dean Tribble <tribble@e-dean.com>
>To: <e-lang@eros-os.org>
>Sent: Sunday, February 11, 2001 3:38 PM
>Subject: [E-Lang] Syntax change: reducing side-effects
>> In the current E language, any name can be assigned unless it is specified
>> as :final.  As is the case with most good programming, however, most names
>> only ever get one value at initialization time, and programmers typically
>> assume that they always have that value.  For example, when you see
>> MintMaker(name) :any {' in the MintMaker program, you ought to be able to
>> assume that the value of the 'MintMaker' binding won't change over
>> time!  But in the current language, it could perfectly well be assigned
>> somewhere later in the module, and then even references to it internal to
>> its code would refer unknowingly to the new MintMaker.  A similar case can
>> be made for most arguments, pattern variables, and even local
>> variables.  Assignment is the fundamental source of race conditions and
>> other non-local dependencies in software systems.
>> To address this problem, I have the following proposal (with help from
>> MarkM and Marcs):
>> We should change the syntax (in as painless a way as possible) so it is
>> statically apparent at name definition time whether a variable could be
>> assigned.
>> Corollary: Assignments can only be made to names that are statically
>> declared as assignable.  All other names are pure, immutable bindings.
>> We went through various unacceptable alternatives which I will summarize
>> the discussion warrants it.  Here I will just propose the one that
>> appears to just work, and has various other unifying effects on the
>> Summary: all defining occurrences of names now default to 'final', unless
>> they are prefixed by 'var', in which case they are settable.  In addition,
>> 'var' can be used as a top-level construct as an alternative to 'define'
>> (equivalent to 'define var').
>> In detail:
>> - This change applies to all defining occurrences of bindings ('define',
>> patterns, argument to methods, etc.)
>> - Reserve the new keyword, 'var'.
>> - For defining occurrence without the 'var' keyword, the guard is always
>> and only a ValueGuard.  If absent, the guard defaults to the ValueGuard,
>> ':any'.  It can be translated into Kernel E as always being wrapped with a
>> 'final' SlotMaker.  The compiler must statically reject assignments to
>> names defined without 'var'.
>> - For defining occurrences that are prefixed with the 'var' keyword, the
>> guard is always a SlotGuard.  If absent, it defaults to ':settable'.
>> - User-defined SlotGuards can only be used with a 'var' prefix.  As a
>> result, the reader of the code (including a compiler) is guaranteed that
>> unless there is a 'var' prefix, the value of the variable will only ever
>> the initial value (i.e., user-defined SlotGuards can allow assignments).
>> - 'var' as the top-level keyword for an expression is equivalent to
>> var'.
>> Below are a few examples.  The only change to MintMaker is in the argument
>> to makePurse which declares the 'balance' instance variable.
>> define MintMaker(name) :any {
>>      define [sealer, unsealer] := BrandMaker pair(name)
>>      define mint {
>>          to printOn(out) { out print(`<$name's mint>`) }
>>          to makePurse(var balance : (any >= 0)) :any {
>>              define decr(amount : (0..balance)) {
>>                  balance -= amount
>>              }
>>              define purse {
>>                  to printOn(out)    { out print(`<has $balance $name
>bucks>`) }
>>                  to getBalance :any { balance }
>>                  to sprout     :any { mint makePurse(0) }
>>                  to getDecr    :any { sealer seal(decr) }
>>                  to deposit(amount : integer, src) {
>>                      unsealer unseal(src getDecr)(amount)
>>                      balance += amount
>> }   }   }   }   }
>> (Note that *I* collapsed the braces to one line :-).
>> The result, however, is that the programmer can know that all the other
>> names (like 'purse', 'mint', 'sealer', etc.) are *in fact* defined once
>> never change, just like they automatically assume, albeit sometimes
>> painfully incorrectly.  Just for the heck of it, I counted the number of
>> changes required in the code in "E in a Walnut" for this change, and there
>> were about 10 'var' declarations required.  Most were as in the example
>> below where they declare mutable instance variables.  The others were in
>> loops that accumulate things.
>> def carMaker new(name) :any {
>>      var xLocation := 0
>>      var yLocation := 0
>>      def car {
>>          to moveTo(x,y) {
>>              xLocation := x
>>              yLocation := y
>>          }
>>          to getX :any {xLocation}
>>          to getY :any {yLocation}
>>          to getName :any {name}
>>      }
>> }
>> The result, however, was that the 100+ other uses of 'def' in the document
>> correctly supported the programmers assumption of immutability!
>> The other big consequence of this is that interpreter and compiler can use
>> that information for substantial performance improvement for the by-far
>> typical case of no assignment.
>> Comments?
>> dean
>> _______________________________________________
>> e-lang mailing list
>> e-lang@mail.eros-os.org
>> http://www.eros-os.org/mailman/listinfo/e-lang
>e-lang mailing list