Expression Closures as Compliment to Arrow Functions

Isiah Meadows impinball at gmail.com
Wed Mar 25 19:40:00 UTC 2015


Would this be rectifiable with something like an unbound lambda type
syntax? You could even make an analogous equivalent for classes.

```js
// Lambda, unbound, ASI applies, same precedence as current arrow functions
() -> foo;
(x) -> bar(1, x);
x -> bar(1, x); // same as previous
(...args) -> foo(this, ...args);
() -> {
  try {
    foo();
    return true;
  } catch (e) {
    return false;
  }
};

// Useful for jQuery, etc.
$('.foo').each(() -> $(this).hide());

// For classes
class Foo {
  // shorthand method, only allowed
  // in ClassBody to limit ambiguity
  bar () -> this.foo.toLowerCase();
  get chars () -> this.bar().split("");
  constructor(foo="") {
    this.foo = foo;
  }
}

// Prototypal
const Foo = {
  bar: () -> this.foo.toLowerCase(),
  get chars () -> this.bar().split(""),
  init: (foo="") -> this.foo = foo,
};

// let foo1 = Object.create(Foo);
// foo1.init();

let foo1 = new Foo();

// let foo2 = Object.create(Foo);
// foo2.init("Foo!");
let foo2 = new Foo("Foo!");

foo1.bar(); // ""
foo2.bar(); // "foo!"
foo1.chars; // []
foo2.chars; // ["f", "o", "o", "!"]
```

I think an unbound lambda like that above would be the best, most flexible
solution. Obviously, some inspiration is taken from CoffeeScript, but it
works.

Also, the syntax would be identical to that of arrow functions, except
substitute the arrow type, "=>" to "->".

Now, as for potential syntax ambiguities, there shouldn't exist any.

- "n-->1" vs "n->1": The character after the first hyphen will decide how
it's parsed. If it's ">", then it represents an unbound arrow function.
- "foo () {}" vs "foo () -> this.bar": If the first character after the
arguments list is an opening curly brace, then it is a concise method. If
it's a hyphen, it's an unbound arrow lambda definition. Same logic for
getters/setters.
- "static foo () {}" vs "static foo () -> bar" vs "static foo () => bar":
see above

These unbound lambdas would be terminated just like arrow functions, and in
classes, the ASI is after the expression statement or block statement.

Basically, the grammar would be otherwise identical to arrow functions,
except for both types can substitute for static method arguments + body and
unbound for instance method arguments + body.

Any interest in this solution? Also, WDYT?

```js
class Foo {
  // This syntax is only allowed in
  // a ClassBody
  foo () -> this;
  foo2 x -> f(this, x);
  foo3 (x, y) -> f(this, x, y);
  get bar () -> this._bar;
  set bar val -> this._bar = 2;
  static baz () => blarg();
  static get quux () => foo();
  static set quux val => foo(val);
}
$(".foo").each(() -> $(this).hide());
list.forEach(x => x * 2);
let f = x => x + 1;
let g = () -> h(this);
```

> From: Brendan Eich <brendan at mozilla.org>
> To: Jacob Parker <jacobparker1992 at gmail.com>
> Cc: es-discuss at mozilla.org
> Date: Wed, 25 Mar 2015 14:30:28 +0100
> Subject: Re: Expression Closures as Compliment to Arrow Functions
> Jacob Parker wrote:
>>
>>
>> Could the comma not be the delimiter, as I think works with arrow
functions, or is that more precedence issues?
>>
>
> No precedence issue, due to AssignmentExpression (not Expression) being
the right-most non-terminal produced by the unbraced alternative for
ConciseBody.
>
> In a class body, comma is the wrong separator (delimiter? trailing comma
allowed in most JS contexts, but still) -- see the live ES7 proposal from
Jeff Morrison, inspired by TypeScript and Flow:
>
> https://gist.github.com/jeffmo/054df782c05639da2adb
>
> Class bodies are not object initialisers, in notable ways, even though
concise methods have the same syntax and (parameterizing `super`
differently according to context) semantics.
>
> Class bodies are not block statements, either, of course. But this
doesn't rule out ; or favor , instead. It just means no ASI insanity. ;-)
>
> /be
>>
>>
>> On Wed, 25 Mar 2015 8:37 am Brendan Eich <brendan at mozilla.org <mailto:
brendan at mozilla.org>> wrote:
>>
>>     Jacob Parker wrote:
>>     > In the context of only objects and classes, is this format no-go?
>>
>>     Without the } that closes a concise method body, there's a new
problem
>>     to-do with computed property names:
>>
>>     class C {
>>        m() this._m
>>        [Symbol.iterator]() {/*...*/}
>>     }
>>
>>     We need a delimiter. Could use ; without ASI, so it'd look like this:
>>
>>     class C {
>>        m() this._m;
>>        [Symbol.iterator]() {/*...*/}
>>     }
>>
>>     I haven't checked for other problems, but wanted to throw this out
and
>>     see if anyone else sees a live one.
>>
>>     /be
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150325/261c3b9c/attachment.html>


More information about the es-discuss mailing list