On 13/09/2011 9:11 AM, Marijn Haverbeke wrote:
Would anyone be opposed to...

A) Marking 'free' blocks (blocks not part of a
function/loop/if/alt/etc, but used solely for a new scope or to do
something before an expression) with a more explicit syntax.

This has the advantage of making them easier to spot and parse
(distinguishing '{ foo; bar; }' from '{mutable foo: bar}' as syntactic
elements isn't hard, but somewhat clunky) and resolving the obscure
ambiguity in 'if fail { blah }' (where {blah} could be an argument to
fail -- or put, or ret). Prefixing these blocks with some keyword
would make it more obvious that they are being used, introduce some
symmetry with other kinds of blocks, and solve these issues. Question
is, which keyword. I wanted to go with 'do' at first, but Brian
pointed out that this is in fact ambiguous. 'block'? 'begin'? 'run'?
Some ascii trick like '%{'?

In order of preference (to me):

  - Use 'val'. Newsqueak (a strong influence on Rust) has a 'val'
    expression form that works this way[1].

  - Use 'do' and remove do-while loops. They're rare anyways and can
    always be rewritten as a somewhat-clunky break:

    'do { ... } while (cond);'

      turns into

    'while (true) { ...; if (!cond) { break; } }'

  - Use 'begin', though I loathe it.

  - Use an ASCII sigil of some sort. I'm still hoping we can get rid
    of the wonky 'ident.' random-ASCII-sigil we're using in alts; adding
    more is pretty unappealing!

-Graydon

[1] This footnote might really interest you! Re-reading the Newsqueak manual (http://swtch.com/~rsc/thread/newsqueak.pdf), I found that their solution to the expr/stmt split is somewhat elegant, and differs from ours. Their approach is that there are statements 'become x' and 'result x', in place of returns and/or expr-stmts. The 'become' statement replaces the entire frame with x (a tail-call-or-return, effectively; we could leave this as 'ret' in absence of tail calls) whereas the 'result' statement stops executing the innermost 'val { ... }' expression and sets its value (as an expression) to x; and it's an error to have a control path in a 'val' block that doesn't have a 'result' statement, same as it would be to fall off the end of a frame.

These two combine in a nice, if chatty, way. The advantages over our scheme are clarity and flexibility: it's not overloading the presence or absence of a semicolon to indicate a block-result value, and you can put 'result' statements in unusual places like if-branches-within-loops that are somewhat difficult for us to express.

So for us, for example:

'let x = val { let y = foo(); y*y }'

  turns into

'let x = val { let y = foo(); res y * y; }'

Obviously more verbose, but less syntactically confusing?

-Graydon
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to