Rascal 中的列表模式匹配
List pattern matching in Rascal
在 Haskell 中(在 Prolog / Erlang 中非常相似),我们可以在列表上定义一个长度函数:
length [] = 0
length (x:xs) = 1 + length xs
在 Rascal 中,我能够使用以下方法创建这样的定义:
int length([]) = 0;
int length([x,xs*]) = 1 + length(xs);
长度递归情况右边的“*”消失了。我知道这可能是有原因的,但我想不通。在 Rascal 中使用模式匹配在列表上定义递归函数是否有更好的方法?
我想解决你问题的多个方面:
- 你的 Rascal 版本看起来不错。 Rascal 比 Haskell 具有更通用的列表模式匹配:不止一个变量可以匹配多个元素,因此列表模式中的每个 "list variable" 都必须用
*
标记以指示仅那。
我们正处于从后缀 * 到前缀 * 的过渡阶段。所以第二条规则可以(以后也应该)写成:
int length([x,*xs]) = 1 + length(xs);
您可能想探索可用于编写各种类似折叠函数的 reducer 表达式:
int length(list[int] xs) = ( 0 | it + 1 | x <- xs );
它由三部分组成:
- 初始值(0);内置变量
it
设置为此初始值。
- 一个累加结果的表达式,可能用到
it
,这里:it + 1
。它具有 it = it + 1
. 的效果
- 生成列表元素的枚举。
- 更一般的(比简单的 head/tail)模式匹配示例如下:
[*x, a]
: 匹配列表末尾的元素
[*x, *x]
: 将列表分成两等份
[*a, x, *b, x, *c]
: 找到两个重复的元素
- 一个绑定列表变量绑定一个完整的列表,你可以像使用任何其他指向列表的变量一样使用它,但是如果你想将它拼接在规则的右侧,你会得到一个更对称的观点:
int length([x,*xs]) = 1 + length([*xs]);
,当然这也是泛化的,所以这样也是可以的:[*xs, 2, *xs]
其中*
操作符只是去掉了一层列表嵌套。
在 Haskell 中(在 Prolog / Erlang 中非常相似),我们可以在列表上定义一个长度函数:
length [] = 0
length (x:xs) = 1 + length xs
在 Rascal 中,我能够使用以下方法创建这样的定义:
int length([]) = 0;
int length([x,xs*]) = 1 + length(xs);
长度递归情况右边的“*”消失了。我知道这可能是有原因的,但我想不通。在 Rascal 中使用模式匹配在列表上定义递归函数是否有更好的方法?
我想解决你问题的多个方面:
- 你的 Rascal 版本看起来不错。 Rascal 比 Haskell 具有更通用的列表模式匹配:不止一个变量可以匹配多个元素,因此列表模式中的每个 "list variable" 都必须用
*
标记以指示仅那。 我们正处于从后缀 * 到前缀 * 的过渡阶段。所以第二条规则可以(以后也应该)写成:
int length([x,*xs]) = 1 + length(xs);
您可能想探索可用于编写各种类似折叠函数的 reducer 表达式:
int length(list[int] xs) = ( 0 | it + 1 | x <- xs );
它由三部分组成:
- 初始值(0);内置变量
it
设置为此初始值。 - 一个累加结果的表达式,可能用到
it
,这里:it + 1
。它具有it = it + 1
. 的效果
- 生成列表元素的枚举。
- 初始值(0);内置变量
- 更一般的(比简单的 head/tail)模式匹配示例如下:
[*x, a]
: 匹配列表末尾的元素[*x, *x]
: 将列表分成两等份[*a, x, *b, x, *c]
: 找到两个重复的元素
- 一个绑定列表变量绑定一个完整的列表,你可以像使用任何其他指向列表的变量一样使用它,但是如果你想将它拼接在规则的右侧,你会得到一个更对称的观点:
int length([x,*xs]) = 1 + length([*xs]);
,当然这也是泛化的,所以这样也是可以的:[*xs, 2, *xs]
其中*
操作符只是去掉了一层列表嵌套。