Patrick (cc'ing rust-dev)-

Between the two options Patrick presented, my vote is for bifurcating the grammar into irrefutable and refutable variants. I like having one operator to denote binding (even if it also sometimes means mutation).

However, my (potentially-wrong) intuition is that the problem Patrick describes is stemming from a not-particularly useful special case of pattern binding.

In particular, I wonder whether the problem could be resolved by not allowing a binding `=` at the topmost level of the pattern.

I mentioned this on IRC last night, but it was late and I'm not convinced I explained myself properly.

More concretely, what I'm suggesting is the following:

What we now write as:

fn main() {
    enum Foo { A((int, int)), B((&'static str, &'static str)) };
    fn visit (x:Foo) {
        match x {
i @ A(j@(k,l)) => io::println(fmt!("an A %? %? %? %?", i, j, k, l)), m @ B(n@(o,p)) => io::println(fmt!("a B %? %? %? %?", m, n, o, p))
        }
    }

    visit(A((1,2)));
    visit(B(("three", "four")));
}

would become illegal. In particular, the bindings for `i` and `m` would be disallowed. But the other bindings would continue to be allowed, and we would switch to the `=` operator for binding, yieldign:

fn main() {
    enum Foo { A((int, int)), B((&'static str, &'static str)) };
    fn visit (x:Foo) {
        match x {
A(j=(k,l)) => io::println(fmt!("an A %? %? %? %?", x, j, k, l)),
            B(n=(o,p)) => io::println(fmt!("a  B %? %? %? %?", x, n, o, p))
        }
    }

    visit(A((1,2)));
    visit(B(("three", "four")));
}


patrick: Does this get rid of the problem, since the `=`'s could only occur beneath pattern structure? Or does it leave the grammar just as ugly as bifurcating it with irrefutable and refutable variants? (Although at least now, even though the grammar is a little more complex, it at least might be *consistent* across both let and match.)

Cheers,
-Felix

On 03/05/2013 03:12, Patrick Walton wrote:
Hi everyone,

There's consensus that `@` (imported from Haskell) is a bad binding operator for patterns, because it leads to the confusing-looking `@@` in, for example:

    struct Foo {
        field: int
    }

    ...

    match foo {
        foo@@Foo { field: x } => ...
    }

However, there is not consensus as to what to change it to. Suggestions are `=` and `as`.

The problem with `=` is that, if implemented naively, it makes our grammar ambiguous:

    let x = y = 3; // is x the result of evaluating `y = 3` (i.e. unit)
                   // or are x and y bound to 3?

The easiest way to fix this problem is to forbid `=` in irrefutable patterns, such as those introduced by `let`. However, this bifurcates the pattern grammar into the irrefutable-pattern grammar and the refutable-pattern grammar, with some conceptually-ugly overlap.

The alternative is `as`, like OCaml. However, this conflicts with `as` in the expression grammar. A subset of the expression grammar is part of the pattern grammar in order to permit matching against constants. Removing `as` expressions from the subset of expression productions permitted in patterns would mean that this would no longer do what you expect:

    match 22.0f32 / 7.0f32 {
        math::PI as f32 => println("Good grief!"),
        _ => {}
    }

So both `=` and `as` have drawbacks.

I don't really have any preference at all; I just need to know what to implement. Opinions?

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


--
irc: pnkfelix on irc.mozilla.org
email: {fklock, pnkfelix}@mozilla.org

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

Reply via email to