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

Reply via email to