【问题标题】:List pattern matching in RascalRascal 中的列表模式匹配
【发布时间】:2017-04-10 12:53:58
【问题描述】:

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

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

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

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

“*”在长度的递归大小写的右侧消失。我知道这可能存在一个原因,但我无法弄清楚。有没有更好的方法来使用 Rascal 中的模式匹配在列表上定义递归函数?

【问题讨论】:

    标签: pattern-matching rascal


    【解决方案1】:

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

    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] 其中* 运算符只是删除了一层列表嵌套。

    【讨论】:

    • 所以......“xs*”将列表的尾部与“xs”匹配。在一个更现实的场景中,我在写一个转换时,首先考虑到列表的尾部会与“xs*”匹配,因此花了几分钟才找到错误。感谢您的回答。我认为在 Rascal Tutor 中提供一个使用列表进行模式匹配的示例会很好(我找不到)。
    • demo::basic::Bubble中有例子。
    • 您还可以在此处找到一些示例:tutor.rascal-mpl.org/Rascal/Rascal.html#/Rascal/Patterns/…。如果你去找导师,这些在 Patterns, Abstract, List 下(这里的抽象意味着不是具体语法上的模式)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    • 2018-10-01
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    相关资源
    最近更新 更多