Context:
References are a specification-level construct that has no
language-level representation in current ES. Reifying
References as objects has been deemed troublesome/
inefficient for implementations.
Problem:
The lack of reified References is a blocking issue when trying
to define control operator libraries: user defined assignment
operators require at least References as arguments, some
operators might want to return References.
I keep running into this limitation, and examples like the '??='
in strawman:default_operator show I'm not the only one. So I
have looked for a workaround, and I think I've found a useful
option, on which I'd like your input.
Suggestion:
The starting point is the representation of References as an
object with a single getter/setter pair, so that reifying, eg.,
base[prop]
gives (*)
let reference = { get deref() { return base[prop] }
, set deref(v) { return base[prop] = v } }
This gives us an object that can be passed around, and can be
reflected back to an r-value or l-value, depending on context:
reference.deref = reference.deref + 1;
Of course, (*) is a handful, and gets worse when one tries to
share computation within 'base' and 'prop' between getter
and setter. No one is going to write this out by hand for every
reified Reference, or read code with lots of these without
struggling to see the simple intention behind the code.
The suggestion is to introduce a keyword phrase, so that
ref base[prop]
desugars to
(function(){
var _base = base; // private symbols _base, _prop;
var _prop = prop; // share evaluation of base, prop
return { get deref() { return _base[_prop] }
, set deref(v) { return _base[_prop] = v } }
}())
(and similarly for the other valid Reference phrases)
Then, a user-defined assignment operator, eg. matching the
strawman:default_operator's '??=', would be possible as
(ignoring infix syntax and multiple evaluation of 'r' here,
as those are separate issues)
function defaultAssign(r,def) {
return (r.deref = r.deref===undefined ? def : r.deref)
}
var x, y = 2;
defaultAssign(ref x,1);
defaultAssign(ref y,1);
// x === 1, y === 2
The readability improvement is so extreme that I doubt
anyone is using this pattern without syntax support?-)
Since reification of References happens only on request,
this has no performance implications for normal operation.
Since reification is a simple desugaring, implementing and
backtranslation into ES5 are not difficult.
Two questions come to mind:
1 where, exactly, does 'ref <Reference>' fit into the syntax
and post-syntax checks for valid References?
2 'ref' is not reserved, what about existing code using 'ref'?
As to 2, if 'ref' is in common use as a variable (a github search [1]
turns up some examples), I wouldn't mind having to import 'ref'
from some standard module before using it as a keyword, or
having local 'ref' declarations disable 'ref' as a keyword. That
way, users can migrate away from 'ref' as a variable, but don't
have to do so unless they want to use 'ref' as a keyword.
From what I can see, syntax support for user-reifiable References
would allow progress with control abstractions in JS, without
having to invoke or wait for the full complexity of macros for JS.
Without something like user-reifiable References, even simple
abstractions like assignment operators remain beyond the
reach of JS library coders.
Thoughts?
Claus
http://clausreinke.github.com/
[1] https://github.com/search?q=ref&type=Code&language=JavaScript
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss