捣蛋鬼图案守卫

时间:2015-05-24 16:13:04

标签: pattern-matching rascal

Rascal是否支持模式保护?

我试图在构建中订购子表达式:

data Expr = and(Expr l, Expr r) | ... ;
Expr and(l, r) | r < l = and(r, l); // fictional syntax for "r < l" guard

如果不支持警卫,那么实施上述措施的最佳方式是什么?

1 个答案:

答案 0 :(得分:1)

为了简化我首先使用int作为lr类型的内容。你想要做的是如下:

rascal>data Expr = and(int l, int r);
ok

rascal>Expr and(int l, int r) = and(r,l) when r < l;
Expr (int, int): rascalfunction()

rascal>and(5,6);
Expr: and(5,6)

rascal>and(6,5);
Expr: and(5,6)

如果创建一个与返回所定义数据类型的构造函数同名的函数(例如Expr),这将允许您执行这种规范化。 when子句表示仅在条件匹配时应用该函数。你可能有一个更复杂的条件,所以如果你有Expr而不是字段的类型,你可以有一个像eval这样的函数来实际计算表达式并返回一个结果。此部分示例(假设您只有一个嵌套级别)如下:

rascal>data Expr = number(int n) | and(Expr l, Expr r);
ok

rascal>int eval(number(int n)) = n;
int (Expr): rascalfunction()

rascal>Expr and(Expr l, Expr r) = and(r,l) when eval(r) < eval(l);
Expr (Expr, Expr): rascalfunction()

rascal>and(number(5),number(6));
Expr: and(
  number(5),
  number(6))

rascal>and(number(6),number(5));
Expr: and(
  number(5),
  number(6))

要使用when,您需要使用函数的此表达式形式,其中您有一个=符号和返回值。如果在规范化中有更复杂的计算,则可以执行以下操作:

Expr and(int l, int r) { 
    if (r < l) {
        return and(r,l); 
    } else {
        fail; 
    }
}

这基本上做同样的事情。如果满足条件,则返回新版本的and。如果不满足条件,fail用于表示我们实际上并不想应用此函数,因此将返回初始值:

rascal>and(5,6);
Expr: and(5,6)

rascal>and(6,5);
Expr: and(5,6)