[E-Lang] Proposed Naming Convention Changes

Terry Stanley tstanley@cocoon.com
Tue, 21 Aug 2001 15:28:25 -0700


We have been grappling with terminology over the past few days and we now 
have a few changes to propose. We expect these changes to make it easier for 
developers to learn E and its distributed computing model, so it is 
important to get them into the next release -- 0.8.10. Please review and 
send comments or questions over the next couple of days, or so.

+++++ Naming conventions for the E developer

It's important to settle on the conventions to follow when naming variables, 
methods, and emakers. We expect to recommend these conventions to the E 
developer and to follow them in our documentation as well. Having a set of 
clear, simple naming conventions will make it easier to write E programs 
that  work in the local case and the remote case.

The current conventions are described in E in a Walnut. In writing the 
example code for the book, marcs found himself taking advantage of E's 
semi-transparency. For example, when he knew that a particular eventual 
reference would resolve to a local (near) reference, he would take advantage 
of this "special knowledge" by making immediate calls on the reference in a 
when-catch block. 

He defined naming conventions to use to make this special knowledge 
explicit. Since E doesn't have static typing, these conventions are used 
when naming variables, methods, and emakers.

Here's a few examples from Walnut. (We don't expect to continue using these 
conventions, but they are fine for examples.)

        car  --  This variable is a near reference; immediate calls can be made

        farCar  --  Assume that this is a remote reference; do eventual sends

        carPromise  --  This promise will resolve to a near reference; 
                                    do eventual sends on the promise;
                                    immediate calls can be made on what it 
                                    resolves to

Think of these names as operational rather than descriptive terms. Their 
purpose is to tell the developer what he can expect to do with the 
reference. The developer needs to know:

        1.  Is this result something I can call?

        2.  Is this result's resolution something I can call?

So, if the variable name is carPromise, the answer to the first question is 
No; the answer to the second is Yes.

You can also think of them as warnings, such as,  "I have special knowledge 
about what I am returning, and you should heed my warning unless you have 
very special knowledge that enables you to confidently disregard my warning."

Naming a variable farCar is a warning to others that unless they have 
special knowledge to the contrary, they should assume that it's a remote 
reference and do eventual sends only.

So, that's the basic idea, but we have used Walnut's conventions for a while 
and there are some things we would like to change.

First of all, Walnut's definitions conflict with definitions in the 
reference taxonomy. The worst case is the use of "promise".

Walnut:           A promise is a reference that when resolved will be near. 

Taxonomy:     A promise is an unresolved reference that can resolve to
                         either a near or far or broken reference.

Being a new E developer, I can say that the inconsistent (and incorrect) use 
of terminology made it much harder than it should have been to learn the 
basics of the distributed computing model.

The reference taxonomy terms are used to describe the different states and 
valid transitions of a reference, whereas the naming conventions must 
reflect the operational distinctions needed when programming.  These must be 
coarser.  Since the name of a variable cannot change when the variable's 
value changes state, the variable name must reflect a set of possible 
states.  (For example, one might think that a variable initially holding a 
promise to foo should be called "fooPromise", but when this promise becomes 
a near reference to foo, the variable's name cannot change to "foo".)  
Therefore, it's best to keep the terminology separate: taxonomy terms should 
not used in the naming conventions and vice versa.

Secondly, a naming convention term needs to be one syllable with 3-4 
characters. ("Vow" is good. "Promise" is bad.)

Here's the proposed changes:

+++++ "vow" replaces "promise" in the conventions.
A vow is a reference that always resolves to a near reference. Use eventual 
sends on the vow and immediate calls on what the vow resolves to.

# pass is defined below
def  testScriptVow := testScriptFilePass <- getText()

when (testScriptVow) -> done(testScript) {
        def format := testScript getFormat()        # immediate call
} catch problem { println(problem) }

Is this result something I can call?    Assume not
Is this result's resolution something I can call?    Yes

The warning is: "Unless you have very special knowledge, you should resolve 
the thing I am returning before making an immediate call."

In the conventions, "vow" replaces "promise" (e.g., carPromise becomes 
carVow) and "promise" will no longer be used in the conventions, and "vow" 
will no longer be used in the taxonomy. If this change is accepted, the 
taxonomy will change its use of LocalVow and RemoteVow to LocalPromise and 
RemotePromise.

+++++ "pass" replaces "far" in the conventions.
A pass is a reference that can resolve to a near or far reference. Use 
eventual sends only. (Think of pass as something that gives authorized access.)

 # file could be local or remote
def testScriptFilePass := testScriptDirPass <- get("evalServer.updoc")       

Is this result something I can call?    Assume not
Is this result's resolution something I can call?    Assume not

The warning is: "Unless you have very special knowledge, you should never 
make an immediate call to what I am returning."

In the conventions, "pass" replaces the use of "far" (e.g., farCar becomes 
carPass) and "far" will no longer be used in the conventions.

+++++ Recommended naming conventions.
Variables and parameters:
    testScript
    testScriptVow
    testScriptPass

Note: as parameter variables, the sense of commitment is reversed.  If a 
method is declared as "to foo(carVow) ...", then the callee is declaring to 
potential callers "I will only do eventual sends on the argument you give me 
until I resolve it.  Once I do resolve it, I will feel free to do immediate 
calls on the resolution, so please give me an argument that satisfies my 
assumptions."

Methods:
    getTestScript()
    getTestScriptVow()
    getTestScriptPass()

Makers:
    testScriptMaker
    testScriptVowMaker
    testScriptPassMaker

Authors:
    testScriptMakerAuthor
    testScriptVowMakerAuthor
    testScriptPassMakerAuthor

+++++ An update.
Before I could send this message off, marcs tried out the new conventions on 
the examples in Walnut -- "vow" is fine but "pass" just doesn't work. He 
thinks we should drop "pass" and instead, use "grip". I like "grip" but it 
seems out-of-character with our other names -- such as "vow". But perhaps we 
can change "vow" to something that is in-character with "grip".

Ideas and comments will be appreciated. Also, thanks to marcs and markm for 
helping out on this.

--Terry