[E-Lang] down with 'define'

Mark S. Miller markm@caplet.com
Mon, 05 Mar 2001 16:38:18 -0800


At 10:40 AM Monday 3/5/01, Ralph Hartley wrote:
>Achhh! I **hate** forward declarations!
>
>To be more precise, I hate languages where one might **need** forward 
>declarations. That the legality, or meaning, of a program should depend on 
>the order in which definitions appear is simply not palatable.

First of all, I'm very sympathetic to this view.  If a way can be found to 
satisfy these concerns within the other constraints of the language, that 
would be great.  Even if we can't satisfy these concerns within the existing 
language, it would be good to understand better why not, and what our 
options are.

Could you give an example of a language that does as you suggest?  I just 
checked Java, and it accepts

        int i = 0;
        i++;

but rejects

        i++;
        int i = 0;

It would significantly help me think about the matter to see a concrete 
language in which the issues raised by scope-order independence have been 
worked out.


>In any reasonable language, names have a scope. Often this is bounded by 
>some sort of block (brackets etc.). It really should always be that way, it 
>should not be bounded by the location of the definition.

In at least the C like languages of which I'm aware, the rule seems to 
approximate "name is in scope from point of introduction until the end of 
block (ie, close curly)".   That's why a Java programmer would not be 
surprised at the above result, and would be surprised if the second sequence 
was accepted and meant the same thing.  E follows in this tradition, but 
much more faithfully that these others.  Perhaps it's E's more uniform 
adherence to this rule that leads to E's problems in this regard?


>It isn't that I use recursive, or mutually recursive, objects that often 
>(though I suspect I do). It is that for any file longer than one editor 
>page, it is not obvious where the piece I am working on is located relative 
>to the definitions that it depends on. Having to worry about the **order** 
>of definitions is just one more task, and it can be substantial. I have 
>enough things to keep track of just remembering how my program is supposed 
>to work.

I like these goals.


>Also, order dependence contradicts the basic semantics of definitions. A 
>definition is a statement of fact, it should have at least some element of 
>timelessness to it. The prototype for a definition is a dictionary entry. 
>With good reason,  dictionaries are not laid out according to the 
>dependencies between the words. Nor is a word used in earlier definitions in 
>any way treated differently from the same word used after its own definition.

Order is space, not time, and is about scoping, not sequence of execution.  
Definitions are statements about *names*, and names (other than those 
reserved by the language) must always be local to a scope.  Therefore these 
statements about names must have a meaning dependent of where the statement 
occurs.

Surely we aren't actually arguing about universal vs scoped statements.  I 
believe we are instead arguing about something like whether the applicable 
scope starts at the point of introduction or at the previous open curly.


>When I see order sensitive definitions, I think that I am just seeing 
>assignments disguised as definitions, not **real** definitions.

Would you apply that to the Java example above?


>I can see lots of reasons why E works the way it does. If you want to use it 
>as a shell language, that use doesn't get along very well with "block 
>structure". You want things to happen right away, not at the "}". There 
>really is a reason for a separation between "shell" languages and those 
>suitable for larger projects (not that shell languages haven't been used for 
>large projects, it just involves pain). You know what happens when you try 
>to please everyone.

The shell-usage issue is indeed one that mixes scope-order and 
time-sequence-of-execution.  However, that's not the source of the 
difficulties.  If these difficulties could be resolved without taking the 
shell-usage issue into account, this would still be great progress.


>>The awkwardness of the section where Walnut explains how to do recursive definition in today's E ("Self-referencing objects" in http://www.skyhunter.com/marcs/ewalnut.html#SEC12 ) makes clear that we have a problem.
>
>
>No joke.
>
>Also, the only mechanism for using definitions in **different** files, that 
>I found in Walnut (emakers), is rather heavyweight. Is that the only way?

I'm glad you raised this.  Currently it is the only way, and it's too 
painful and urgently needs improvement.  There seems to be a whole subfield 
of language design on the design of "module" systems, but I am currently a 
lightweight in this literature.  The issues to be taken into account are at 
least the usual ones: separate compilation, principled scoping, ease of use.

Also, because we've currently living on the Java platform, a separately 
compiled E module/emaker would likely be compiled into a Java *.class file, 
so a Java-based module system for E needs to live well within the resulting 
constraints, if any.


>Of course, I know that for E it is almost certainly way too late for the 
>sort of basic redesign that would be needed to fix this properly. I guess 
>I'll just have to wait for "F".

It's very possible.  Y'all have just seen me reject other suggestions on 
these grounds.  But I think the issues you raised are worth exploring until 
we at least get a feel for whether the required changes would be too 
painful.  If you like, I can't reject it until I know what it is. ;)  

Sometimes the universe gives us happy surprises:  Sometimes conceptually 
large changes are simply to understand and easy implement, as when I 
implemented Dean's "var" suggestion in a hour or so.


        Cheers,
        --MarkM