I am not a big fan of the `if` syntax. Or at least I don't mind our current one and it is nicely unambiguous. However, I really like "alt with arrow" syntax. I find the current one quite unreadable, particularly for long blocks. The "=>" arrow (or `->`, I am somewhat indifferent) helps to set apart the conditions and the blocks.

Here is a random example to illustrate what I mean:

Before:

            alt elsopt {
              some(els) {
                let if_t = fcx.next_ty_var();
                let thn_bot = check_block(fcx, thn);
                let thn_t = fcx.node_ty(thn.node.id);
                demand::simple(fcx, thn.span, if_t, thn_t);
                let els_bot = check_expr_with(fcx, els, if_t);
                (if_t, thn_bot & els_bot)
              }
              none {
                check_block_no_value(fcx, thn);
                (ty::mk_nil(fcx.ccx.tcx), false)
              }
            };

After:

            alt elsopt {
              some(els) => {
                let if_t = fcx.next_ty_var();
                let thn_bot = check_block(fcx, thn);
                let thn_t = fcx.node_ty(thn.node.id);
                demand::simple(fcx, thn.span, if_t, thn_t);
                let els_bot = check_expr_with(fcx, els, if_t);
                (if_t, thn_bot & els_bot)
              }
              none => {
                check_block_no_value(fcx, thn);
                (ty::mk_nil(fcx.ccx.tcx), false)
              }
            };

I personally find the second example quite a bit easier to read. In the first, my eyes get lost and I have trouble distinguishing the patterns from the code.

It is also much nicer for small alts, for example:

        let pass1 = alt ty::get(self.self_ty).struct {
          ty::ty_param(n, did) {
            self.method_from_param(n, did)
          }
          ty::ty_iface(did, tps) {
            self.method_from_iface(did, tps)
          }
          ty::ty_class(did, tps) {
            self.method_from_class(did, tps)
          }
          _ {
            none
          }
        };

becomes:

        let pass1 = alt ty::get(self.self_ty).struct {
          ty::ty_param(n, did) => self.method_from_param(n, did)
          ty::ty_iface(did, tps) => self.method_from_iface(did, tps)
          ty::ty_class(did, tps) => self.method_from_class(did, tps)
          _ => none
        };

So I propose we make the syntax for an alt arm be:

    alt := `alt` expr { arm* }
    arm := pattern => expr


Niko

On 4/11/12 1:28 PM, Patrick Walton wrote:
Here's a total bikeshed. Apologies in advance:

There's been some criticism of Rust's syntax for being too brace-heavy. I've been thinking this for a while. Here's a minimal delta on the current syntax to address this:

Examples:

    // before:
    if foo() == "bar" { 10 } else { 20 }

    // after:
    if foo() == "bar" then 10 else 20
    // or:
    if foo() == "bar" { 10 } else { 20 }

    // before:
    alt foo() {
        "bar" { 10 }
        "baz" { 20 }
        "boo" { 30 }
    }

    // after:
    alt foo() {
        "bar" => 10,
        "baz" => 20,
        "boo" => 30
    }
    // or:
    alt foo() {
        "bar" { 10 }
        "baz" { 20 }
        "boo" { 30 }
    }

BNF:

    if ::== "if" expr ("then" expr | block) ("else" expr)?
    alt ::== "alt" expr "{" (arm* last-arm) "}"
    arm ::== block-arm | pat "=>" expr ","
    last-arm ::== block-arm | pat "=>" expr ","?
    block-arm ::== pat block

You can think of it this way: We insert a "then" before the then-expression of each if; however, you can omit it if you use a block. We also insert a "=>" before each expression in an alt arm and a "," to separate expressions from subsequent patterns; however, both can be omitted if the arm expression is a block.

This does, unfortunately, create the dangling else ambiguity. I'm not sure this is much of a problem in practice, but it might be an issue.

The pretty printer would always omit the "then" and the "=>"/"," when the alt arm is a block. That way, we aren't introducing multiple preferred syntactic forms of the same Rust code (which I agree is generally undesirable); the blessed style is to never over-annotate when a "then" body or an alt expression is a block.

Here's an example piece of code (Jonanin's emulator) written before-and-after:

Before: https://github.com/Jonanin/rust-dcpu16/blob/master/asm.rs
After: https://gist.github.com/2360838

Thoughts?

Patrick
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to