User-reifiable References

Claus Reinke claus.reinke at talk21.com
Tue Jul 31 09:26:40 PDT 2012


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
 


More information about the es-discuss mailing list