TCP?

# Herby Vojčík (13 years ago)

Hello.

Question 1: Do people want it? Do TC39 plan to have it in ES.next?

Question 2: If yes and yes, what form is preferrable? (below I show all value-producing code-block structures grouped)

  • lambda blocks?

    function (x) { return this.plain_dynamic; } x => this.bound(x) {|| /TCP/ return this.bound_result; } {|y| /TCP/ if (a < y) return; a += y } do { while (x % 2 === 0) { x /= 2; } x }

  • parametrized do expressions?

    function (x) { return this.plain_dynamic; } x => this.bound(x) do () { /TCP/ return this.bound_result; } do (y) { /TCP/ if (a < y) return; a += y } do /immediately/ { while (x % 2 === 0) { x /= 2; } x }

  • something else?

# Brendan Eich (13 years ago)

Herby Vojčík wrote:

Question 1: Do people want it? Do TC39 plan to have it in ES.next?

No, not in the block-lambda TCP sense. See my mail of 7:11am today. At most the desire is for an equivalence over expressions, not statements:

e ~= do { e; }

So |this| must work, and we ban 'arguments' and 'yield' in arrow bodies.

I forgot to mention 'yield' in the 7:11am mail -- it was good catch by Mark. Generators require a * in the head, after function or before the generator function's name. Arrows cannot be generators, there's no place for the * and YAGNI. Therefore 'yield' is not allowed, as it breaks the expression-TCP equivalence, and restoring that equivalence would mean deep continuations, which we have ruled out for years.

# Brendan Eich (13 years ago)

Brendan Eich wrote:

I forgot to mention 'yield' in the 7:11am mail -- it was good catch by Mark. Generators require a * in the head, after function or before the generator function's name. Arrows cannot be generators, there's no place for the * and YAGNI. Therefore 'yield' is not allowed, as it breaks the expression-TCP equivalence, and restoring that equivalence would mean deep continuations, which we have ruled out for years.

I updated

strawman:arrow_function_syntax

to ban 'yield' as well as 'arguments' in arrow bodies.

# Mark S. Miller (13 years ago)

We are achieving a weaker form of almost-TCP that is close enough to have many nice properties.

e is like (()=>(e))()

for programs which are not not statically rejected, except for "return".

The other TCP violations:

  • lexical this fixes the "this" violation.
  • banning a free[1] "arguments", "yield", "break", "continue", "break" <label>, "continue" <label> in e on the right prevents these TCP violations

from occurring in statically accepted programs.

In listing these, I realize just now that we missed one from the discussion yesterday. Does "var" hoist across a "=>"? The two

weak-almost-TCP-respecting answers are "yes" and "programs with such 'var' occurrences are statically rejected". I hope we find time to discuss this today.

[1] By "free" in this context, I mean an occurrence that, if allowed and attributed TCP semantics, would effectively be a use occurrence referring to a defining occurrence in the lexical context outside the closure. For example, a "break" <label> referring to an unshadowed label on the block

containing the closure.

What's very nice about sweeping TCP violations under this static rejection rug is that it is 100% upwards compatible for a future version of the language to allow these later with TCP semantics. For me, the most attractive is "break" <label>;

in order to give us a non-exceptional non-local exit. But the real need is actually for non-local-exit-with-value (John Reynold's "escape" or Scheme's "call/ec" -- call with escape continuation), for which I have no concrete proposal.

# Andreas Rossberg (13 years ago)

On 29 March 2012 17:11, Mark S. Miller <erights at google.com> wrote:

In listing these, I realize just now that we missed one from the discussion yesterday. Does "var" hoist across a "=>"?

Ah, nice, that's a good one, too.

The two weak-almost-TCP-respecting answers are "yes" and "programs with such 'var' occurrences are statically rejected". I hope we find time to discuss this today.

Hold on, do you even view the former as an option? Seems like it would be a major foot torpedo for sure. Even considering the idea makes me cringe... :)

I'd be happy to disallow 'var' in lambda bodies, but I don't know how well that flows with the code transitioning argument.

# Mark S. Miller (13 years ago)

On Thu, Mar 29, 2012 at 8:30 AM, Andreas Rossberg <rossberg at google.com>wrote:

On 29 March 2012 17:11, Mark S. Miller <erights at google.com> wrote:

In listing these, I realize just now that we missed one from the discussion yesterday. Does "var" hoist across a "=>"?

Ah, nice, that's a good one, too.

The two weak-almost-TCP-respecting answers are "yes" and "programs with such 'var' occurrences are statically rejected". I hope we find time to discuss this today.

Hold on, do you even view the former as an option? Seems like it would be a major foot torpedo for sure. Even considering the idea makes me cringe... :)

Agreed. I make this abstract argument on the way to advocating the static rejection option, as you guessed.

I'd be happy to disallow 'var' in lambda bodies, but I don't know how well that flows with the code transitioning argument.

Transition "var"s into "const"s, "let"s, and "function"s prior to transitioning blocks into closures.

In fact, I'd recommend transitioning "var"s into "const"s, "let"s, and "function"s prior to getting out of bed in the morning ;).

# Brendan Eich (13 years ago)

Mark S. Miller wrote:

e is like (()=>(e))()

Nit: no need to over-parenthesize the e in the right-hand side:

e is like (() => e)()

(Andreas raised this at the end of the meeting but said "function" at first before correcting to "arrow function" -- big difference! ;-)

In listing these, I realize just now that we missed one from the discussion yesterday. Does "var" hoist across a "=>"? The two weak-almost-TCP-respecting answers are "yes" and "programs with such 'var' occurrences are statically rejected". I hope we find time to discuss this today.

I disagree that we missed 'var'. Remember, e means expression here, not statement or declaration (and deferring consideration of do-expressions).

But to address this point as if 'var' were legal in an expression:

We could say "no var in arrow function block bodies". That would be a bit of a migration tax, but plausible for let-boosting via var-deprecation. I'm generally against splitting the language into further subsets

Or we could say "var hoists to top of body-block, just as in old-school functions".

I see no reason to want var hoisting out of an arrow-body into its enclosing old-function or program, though. Remember, these are not lambdas in any sense we've considered. They're arrow-functions. :-)