Why not just move Arrow to the head to avoid any current or future
ArrowFormalParameters parsing issues such as the GLR issue ?
ArrowFunctionExpression :
Arrow ArrowFormalParametersOpt InitialValue
Arrow ArrowFormalParametersOpt BlockOpt
This would deviate from C# and Coffeescript tradition, but I think
even for people familiar with those languages it would be an easy
transition. They could potentially be called "arrowhead" functions as
a mnemonic device for the arrow position if necessary.
Here's what the examples from the arrow function syntax strawman [1]
would then look like:
// Empty arrow function is minimal-length
let empty = ->;
// Expression bodies needs no parentheses or braces
let identity = -> (x) x;
// Fix: object initialiser need not be parenthesized, see Grammar Changes
let key_maker = -> (val) {key: val};
// Nullary arrow function starts with arrow (cannot begin statement)
let nullary = -> preamble + ': ' + body;
// No need for parens even for lower-precedence expression body
let square = -> (x) x * x;
// Statement body needs braces, must use 'return' explicitly if not void
let oddArray = [];
array.forEach( -> (v, i) { if (i & 1) oddArray[i >>> 1] = v; });
// Use # to freeze and join to nearest relevant closure
function return_pure() {
return # -> (a) a * a;
}
let p = return_pure(),
q = return_pure();
assert(p === q);
function check_frozen(o) {
try {
o.x = "expando";
assert(! "reached");
} catch (e) {
// e is something like "TypeError: o is not extensible"
assert(e.name == "TypeError");
}
}
check_frozen(p);
function partial_mul(a) {
return # -> (b) a * b;
}
let x = partial_mul(3),
y = partial_mul(4),
z = partial_mul(3);
assert(x !== y);
assert(x !== z);
assert(y !== z);
check_frozen(x);
check_frozen(y);
check_frozen(z);
// Use ''=>'' (fat arrow) for lexical ''this'', as in CoffeeScript
// ("fat" is apt because this form costs more than ''->'')
const obj = {
method: function () {
return => this;
}
};
assert(obj.method()() === obj);
// And *only* lexical ''this'' for => functions
let fake = {steal: obj.method()};
assert(fake.steal() === obj);
// But ''function'' still has dynamic ''this''
let real = {borrow: obj.method};
assert(real.borrow()() === real);
// Recap:
// use ''->'' instead of ''function'' for lighter syntax
// use ''=>'' instead of calling bind or writing a closure
const obj2 = {
method: -> () (=> this)
};
assert(obj2.method()() === obj2);
let fake2 = {steal: obj2.method()};
assert(fake2.steal() === obj2);
let real2 = {borrow: obj2.method};
assert(real2.method()() === real2);
// An explicit ''this'' parameter can have an initializer
// Semantics are as in the "parameter default values" Harmony proposal
const self = {c: 0};
const self_bound = -> (this = self, a, b) {
this.c = a * b;
};
self_bound(2, 3);
assert(self.c === 6);
const other = {c: "not set"};
self_bound.call(other, 4, 5);
assert(other.c === "not set");
assert(self.c === 20);
// A special form based on the default operator proposal
const self_default_bound = -> (this ??= self, a, b) {
this.c = a * b;
}
self_default_bound(6, 7);
assert(self.c === 42);
self_default_bound.call(other, 8, 9);
assert(other.c === 72);
assert(self.c === 42);
// ''=>'' is short for ''->'' with an explicit ''this'' parameter
function outer() {
const bound = => () this;
const bound2 = -> (this = this) this; // initializer has outer
''this'' in scope
const unbound = -> () this;
const unbound2 = -> (this) this;
return [bound, bound2, unbound, unbound2];
}
const t = {},
u = {};
const v = outer.call(t);
assert(v[0]() === t);
assert(v[1]() === t);
assert(v[2]() === t);
assert(v[3]() === t);
assert(v[0].call(u) === t);
assert(v[1].call(u) === t);
assert(v[2].call(u) === u);
assert(v[3].call(u) === u);
// Object intialiser shorthand: "method" = function-valued property
with dynamic ''this''
const obj = {
method -> () {
return => this;
}
};
// Name binding forms hoist to body (var) or block (let, const) top
var -> warmer(a) {...};
let -> warm(b) {...};
const -> colder(c) {...};
const # -> coldest(d) {...};
Also, why not allow the explicit this parameter with current function
syntax as well via:
ArrowFunctionExpression :
Arrow FormalParametersOpt InitialValue
Arrow FormalParametersOpt BlockOpt
FunctionDeclaration :
function Identifier FormalParameters { FunctionBody }
FunctionExpression :
function IdentifierOpt FormalParameters { FunctionBody }
FormalParameters :
( FormalParameterListOpt )
FormalParameterList : ...
this InitialiserOpt
this InitialiserOpt , FormalParameterList
[1] http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax
Thanks,
Sean Eagan
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss