For the purposes of the current ES4-WG discussion, here is a proposal to
drop packages
At the last f2f Waldemar raised pertinent questions about
whether the desugaring of packages (in their current form)
into namespaces would work.
The answer appears to be, for the time being, no. One
important problem, for example, is that packages appear
to be scoped entities but are not. This fragment of code:
package P {
public var x
}
means exactly the same thing as this fragment:
package Q {
}
public var x
and that leads you into trouble when you start using
import. Consider a third package R:
package R {
external var x
}
Now import R into P and Q and reference x:
package P {
import R.*;
public var x;
... x ...
}
package Q {
import R.*;
... x ...
}
public var x
Now the intent of the reference in Q is clearly meant to be
to R.x, and the (outer) public::x should not be allowed to
change that intent (consider that public::x is introduced in
some later file, at a later time) while the most reasonable
behavior for P is that x references public::x (it's in the same
block as the reference, therefore "closer" or more obvious --
take your pick). The desired behavior is not the same in the
two cases, yet the two fragments mean the same thing.
It's possible to construct even more fun examples with lexically
nested import statements.
It may be possible to fix this by introducing arcane
restrictions (consider flagging the reference to x in P as
ambiguous) but not, probably, as a pure desugaring to
namespaces, and even then it's not clear how useful the
package abstraction would be.
As a consequence Jeff and I think we should remove packages
from ES4 for the time being, instead of embarking on a design
exercise without the benefit of practice. Concretely, we
propose the following:
the 'package', 'import', and 'external' keywords and forms
are removed from the language along with the dotted-name
syntax for packages
the notion of top-level blocks (which was only required
to model the desugaring) is removed from the language
"use default namespace" is allowed anywhere at the top level
of the program and at the top level of class blocks (and its
effect extends to the end of the program or class or until
a new "use default namespace" pragma is seen)
"use namespace" is allowed anywhere at the top level of any
block (including program and class blocks) and its effect
extends to the end of the program or block
the keyword 'internal' persists, but its value is now an
unforgeable namespace that is private to the compilation unit
(script, file, etc).
The net effect is simplification and actually better integrity,
since the file-private unforgeable namespace allows programs truly
to hide definitions in a file. (Our "local package" mechanism
provided something similar but that proposal appears to have fallen
by the wayside.)
The mechanisms proposed above are sufficient to emulate simple
packages a la Java. Consider an evaluator package that has a
statement evaluator in one file and an expression evaluator in
another:
// file 1
internal namespace PRIVATE = "eval private"
internal namespace PUBLIC = "eval public"
use namespace PRIVATE, namespace PUBLIC
PUBLIC function evaluate(t)
evalStmt(t)
PRIVATE function evalStmt(t)
... evalExpr(t) ...
// file 2
internal namespace PRIVATE = "eval private"
internal namespace PUBLIC = "eval public"
use namespace PRIVATE, namespace PUBLIC
Perhaps, with some experience, a lightweight syntax could be
added to ES4 to make that kind of evaluation simpler, but that's
not what we're proposing at this time.
--lars
------ End of Forwarded Message
For the purposes of the current ES4-WG discussion, here is a proposal to
drop packages
-----
At the last f2f Waldemar raised pertinent questions about
whether the desugaring of packages (in their current form)
into namespaces would work.
The answer appears to be, for the time being, no. One
important problem, for example, is that packages appear
to be scoped entities but are not. This fragment of code:
package P {
public var x
}
means exactly the same thing as this fragment:
package Q {
}
public var x
and that leads you into trouble when you start using
import. Consider a third package R:
package R {
external var x
}
Now import R into P and Q and reference x:
package P {
import R.*;
public var x;
... x ...
}
package Q {
import R.*;
... x ...
}
public var x
Now the _intent_ of the reference in Q is clearly meant to be
to R.x, and the (outer) public::x should not be allowed to
change that intent (consider that public::x is introduced in
some later file, at a later time) while the most reasonable
behavior for P is that x references public::x (it's in the same
block as the reference, therefore "closer" or more obvious --
take your pick). The desired behavior is not the same in the
two cases, yet the two fragments mean the same thing.
It's possible to construct even more fun examples with lexically
nested import statements.
It may be possible to fix this by introducing arcane
restrictions (consider flagging the reference to x in P as
ambiguous) but not, probably, as a pure desugaring to
namespaces, and even then it's not clear how useful the
package abstraction would be.
As a consequence Jeff and I think we should remove packages
from ES4 for the time being, instead of embarking on a design
exercise without the benefit of practice. Concretely, we
propose the following:
- the 'package', 'import', and 'external' keywords and forms
are removed from the language along with the dotted-name
syntax for packages
- the notion of top-level blocks (which was only required
to model the desugaring) is removed from the language
- "use default namespace" is allowed anywhere at the top level
of the program and at the top level of class blocks (and its
effect extends to the end of the program or class or until
a new "use default namespace" pragma is seen)
- "use namespace" is allowed anywhere at the top level of any
block (including program and class blocks) and its effect
extends to the end of the program or block
- the keyword 'internal' persists, but its value is now an
unforgeable namespace that is private to the compilation unit
(script, file, etc).
The net effect is simplification and actually better integrity,
since the file-private unforgeable namespace allows programs truly
to hide definitions in a file. (Our "local package" mechanism
provided something similar but that proposal appears to have fallen
by the wayside.)
The mechanisms proposed above are sufficient to emulate simple
packages a la Java. Consider an evaluator package that has a
statement evaluator in one file and an expression evaluator in
another:
// file 1
internal namespace PRIVATE = "eval private"
internal namespace PUBLIC = "eval public"
use namespace PRIVATE, namespace PUBLIC
PUBLIC function evaluate(t)
evalStmt(t)
PRIVATE function evalStmt(t)
... evalExpr(t) ...
// file 2
internal namespace PRIVATE = "eval private"
internal namespace PUBLIC = "eval public"
use namespace PRIVATE, namespace PUBLIC
PRIVATE function evalExpr(t)
... evalStmt(t) ...
// file 3 (client)
namespace EVAL = "eval public"
use namespace EVAL // import EVAL.*
print(evaluate(read()))
Perhaps, with some experience, a lightweight syntax could be
added to ES4 to make that kind of evaluation simpler, but that's
not what we're proposing at this time.
--lars
------ End of Forwarded Message
For the purposes of the current ES4-WG discussion, here is a proposal to drop packages
At the last f2f Waldemar raised pertinent questions about whether the desugaring of packages (in their current form) into namespaces would work.
The answer appears to be, for the time being, no. One important problem, for example, is that packages appear to be scoped entities but are not. This fragment of code:
package P { public var x }
means exactly the same thing as this fragment:
package Q { } public var x
and that leads you into trouble when you start using import. Consider a third package R:
package R { external var x }
Now import R into P and Q and reference x:
package P { import R.*; public var x; ... x ... }
package Q { import R.*; ... x ... } public var x
Now the intent of the reference in Q is clearly meant to be to R.x, and the (outer) public::x should not be allowed to change that intent (consider that public::x is introduced in some later file, at a later time) while the most reasonable behavior for P is that x references public::x (it's in the same block as the reference, therefore "closer" or more obvious -- take your pick). The desired behavior is not the same in the two cases, yet the two fragments mean the same thing.
It's possible to construct even more fun examples with lexically nested import statements.
It may be possible to fix this by introducing arcane restrictions (consider flagging the reference to x in P as ambiguous) but not, probably, as a pure desugaring to namespaces, and even then it's not clear how useful the package abstraction would be.
As a consequence Jeff and I think we should remove packages from ES4 for the time being, instead of embarking on a design exercise without the benefit of practice. Concretely, we propose the following:
the 'package', 'import', and 'external' keywords and forms are removed from the language along with the dotted-name syntax for packages
the notion of top-level blocks (which was only required to model the desugaring) is removed from the language
"use default namespace" is allowed anywhere at the top level of the program and at the top level of class blocks (and its effect extends to the end of the program or class or until a new "use default namespace" pragma is seen)
"use namespace" is allowed anywhere at the top level of any block (including program and class blocks) and its effect extends to the end of the program or block
the keyword 'internal' persists, but its value is now an unforgeable namespace that is private to the compilation unit (script, file, etc).
The net effect is simplification and actually better integrity, since the file-private unforgeable namespace allows programs truly to hide definitions in a file. (Our "local package" mechanism provided something similar but that proposal appears to have fallen by the wayside.)
The mechanisms proposed above are sufficient to emulate simple packages a la Java. Consider an evaluator package that has a statement evaluator in one file and an expression evaluator in another:
// file 1 internal namespace PRIVATE = "eval private" internal namespace PUBLIC = "eval public" use namespace PRIVATE, namespace PUBLIC
PUBLIC function evaluate(t) evalStmt(t)
PRIVATE function evalStmt(t) ... evalExpr(t) ...
// file 2
internal namespace PRIVATE = "eval private" internal namespace PUBLIC = "eval public" use namespace PRIVATE, namespace PUBLIC
PRIVATE function evalExpr(t) ... evalStmt(t) ...
// file 3 (client)
namespace EVAL = "eval public" use namespace EVAL // import EVAL.*
print(evaluate(read()))
Perhaps, with some experience, a lightweight syntax could be added to ES4 to make that kind of evaluation simpler, but that's not what we're proposing at this time.
--lars
------ End of Forwarded Message