在Rascal中列出模式匹配

时间:2017-04-10 12:53:58

标签: pattern-matching rascal

在Haskell中(在Prolog / Erlang中非常相似),我们可以在列表上定义一个长度函数:

length [] = 0
length (x:xs) = 1 + length xs

在Rascal中,我能够使用以下方法创建这样的定义:

int length([]) = 0;
int length([x,xs*]) = 1 + length(xs);

" *"消失在递归长度的右侧。我知道它可能存在这个原因,但我无法理解。是否有更好的方法在Rascal中使用模式匹配在列表上定义递归函数?

1 个答案:

答案 0 :(得分:2)

我想解决您的问题的各个方面:

  1. 你的Rascal版本看起来很好。 Rascal具有比Haskell更通用的列表模式匹配:多个变量可以匹配多个元素,因此每个"列表变量"在列表模式中必须使用*标记,以表明这一点。
  2. 我们处于过渡阶段,我们正在从后缀*转移到前缀*。所以第二条规则可以(并且将来应该)写成:

    int length([x,*xs]) = 1 + length(xs);

  3. 您可能想要探索可用于编写各种类似折叠函数的 reducer表达式

    int length(list[int] xs) = ( 0 | it + 1 | x <- xs );

    它由三部分组成:

    • 初始值(0);内置变量it设置为此初始值。
    • 一个累积结果且可能使用it的表达式,此处为:it + 1。它的效果为it = it + 1
    • 生成列表元素的枚举。
  4. 更一般(比简单的头/尾)模式匹配示例如下:
    • [*x, a]:匹配列表末尾的元素
    • [*x, *x]:将列表分成两等份
    • [*a, x, *b, x, *c]:找到两个重复的元素
  5. 绑定列表变量绑定一个完整列表,您可以像指向列表的任何其他变量一样使用该列表,但如果要将其拼接在规则的右侧,则会获得更加对称的视图: int length([x,*xs]) = 1 + length([*xs]);,当然这也是一般化的,所以这也是可能的:[*xs, 2, *xs]其中*运算符只是删除了一层列表嵌套。