[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