it-swarm-ja.com

CでRusts`match`のような構造を実装しますか?

私はCにコンパイルするコンパイラーを書いています。私がやろうとしていることの1つは、Rustの一致のような構造を実装することです。

// { some function
    let mut foo = 32;
    match foo {
        3 => return "hey",
        4 | 5 | 6 => return "foo",
        9 ... 12 => return "blah",
        _ => return "bar",
    }
// }

このような構造はCコードでどのように見えますか?私はこのような単純なものが次のようなスイッチ構造である可能性があると考えていました:

switch (foo) {
    case 3: return "hey";
    case 4: case 5: case 6: return "foo";
    case 9: case 10: case 11: case 12: return "blah";
    default: return "bar";
}

そして最も重要なのは、次のようなより複雑な例をどのように探すかです。

let pair = (0, -2);

match pair {
    (0, y) => println!("First is `0` and `y` is `{:?}`", y),
    (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
    _      => println!("It doesn't matter what they are"),
}

タプルが分解され、値も処理できる場所はどこですか?

5
Jon Flow

超基本的な例を考えてみましょう。あなたの言語には、intpairの2つのタイプしかありません。ペアは他のペアを保持できます。 「ケース」には、バインドされていない変数もあります。

したがって、一致する値を渡すと、intまたはpairを持つことができます。一致するパターンは、intpair、または非バインド変数にすることができます。次に、パターンマッチングアルゴリズムは次のようになります。

if my pattern is an int, and the input is an int, if they're equal, do this.
if my pattern is a var, assign the value to the var, and do this.
if my pattern is a pair, and the input is a pair, then if 
    pattern-match(pattern.first, value.first) && 
    pattern-match(pattern.second, value.second), do this.
otherwise, try the next pattern.

シンボルとペアしかない基本的なLispの場合、必要なのはそれだけです。他の言語の場合、他のタイプや他の構造を処理するために基本を拡張する必要があるかもしれません。

そしてうまくいけば、変更可能な状態になると、これがどのように危険になるかを見ることができます。

4
Telastyn