像Rust这样的语言如何实现匹配?

8

我不是一个函数式编程者,所以对于模式匹配、模式或其他与此相关的东西并不太熟悉。在我看来,我只了解传统的 switch 语句的概念。

编译器如何实现 match 语句?match 与 switch 的区别是什么?GNU C99 扩展允许在 switch 的 case 中使用范围,那么这与以下有什么区别:

match x {
    0 ... 9 => ...,
    _ => ...,
}

并且
switch (x) {
case 0 ... 9: ...; break;
default: ...; break;
}

请注意,第二段代码是带有GNU扩展的简单的C语言开关语句。
1个回答

15

对常量值的模式匹配可以实现为跳转表或一系列条件跳转 - 就像 switch 语句一样。允许范围并不会改变这种情况。

Rust 枚举(至少具有成员的枚举)被实现为带标记的联合体,即包含标记和包含成员的结构体的联合体。

然后,对枚举的模式匹配就简单地被翻译为对其标记的 switch(同时将模式绑定的变量绑定到联合体的成员)。所以 Rust 代码中的这个东西:

enum Result {
  SingleResult(i32),
  TwoResults(i32, i32),
  Error
}

match someResult {
  Result::SingleResult(res) => f(res),
  Result::TwoResults(res1, res2) => g(res1, res2),
  Result::Error => error()
}

会被翻译成与以下C代码相同的机器码(大概率):

struct Result {
  enum {
    SingleResult, TwoResults, Error
  } tag;
  union {
    struct {
      int arg1;
    } singleResult;
    struct {
      int arg1;
      int arg2;
    } twoResults;
  } value;
};

switch(someResult.tag) {
  case SingleResult: {
    int res = someResult.value.singleResult.arg1;
    f(res);
    break;
  }
  case TwoResults: {
    int res1 = someResult.value.twoResults.arg1;
    int res2 = someResult.value.twoResults.arg2;
    g(res1, res2);
    break;
  }
  case Error: {
    error();
    break;
  }
}

那很有道理。谢谢! - Jon Flow
你有任何参考资料或相关源代码来支持这个吗? - Tyler Davis
1
@TylerDavis 不是,但我查看了生成的代码以进行验证。 - sepp2k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接