[NB: I agree with Mark that we should not focus too much on concrete syntax yet, so I'll also plead for people to avoid quibbling with details of syntax for the moment.]

Instead of "reveal" I'd prefer block expressions with a fixed (but optional) tail expression:

    BlockExpr ::= "{" (Stmt|Decl)* ("=>" Expr)? "}"

The semantics would be like a block statement, but the result value is the result of the tail expression, or the undefined value if it's omitted. The tail expression would be in the same scope chain as the whole block but would be a mandatory tail call.

This would be used for the body of lambdas, and addresses Waldemar's concern about unintended leakage. It admits an extremely simple definition of tail position.

Moreover, it could be part of a let expression form:

    Expr ::= ... | "let" LetHead BlockExpr

This single form functions as an expression or a statement, without the need for two separate forms. (MarkM would probably like for the LetHead to be optional, which is unproblematic but a detail we can postpone discussing.)

    function foo(x) {
        // let expression used as an expression
        frob(let (y = x + 1) {
                 print("hello, world!");
                 => baz(y)
             });
    }

    function bar(x) {
        // let expression used as a statement
        let (y = x + 1) {
            f(x); g(y); h(x,y);
        }
    }

To contrast with "reveal": when there's mutable state I'd prefer it to be explicit. Anything you might do with reveal you could do with let expressions using a local variable. For example:

    lambda(x){ if (p()) reveal(1); else reveal(2); }

could be expressed as

    lambda(x) { let tmp; if (p()) tmp = 1; else tmp = 2; => tmp }

As I say, I prefer not to hide the mutation.

Dave
_______________________________________________
Es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to