在函数参数中使用模式匹配

Use pattern matching in function parameters

我想知道是否可以指定作为参数传递给函数的节点的确切构造函数。例如,如果在 lang::java::m3::AST::Declaration ADT 中,我将一个我知道必须是 \class() 的节点传递给一个函数,有没有办法指定它?

现在我有:

public void foo(lang::java::m3::AST::Declaration dec) { ... }

但我想要类似的东西:

public void foo(lang::java::m3::AST::\class(a,b,c,d) dec) { ... }

这样我就不必在 foo 内部进行匹配来到达 class 节点的部分。

或者,是否有其他更有效的方法。

谢谢!

当然可以,而且您可以将完整的模式匹配作为参数,而不必提及完整路径:

void foo(class(str a, str b, str c, list[Decl] d)) { ... }

或者也将 e 绑定到完整的 class 声明:

void foo(Decl e:class(str a, str b, str c, list[Decl] d)) { ... }

请注意,模式中的开放变量需要输入类型(与模式嵌套在函数体内时不同),这是因为我们不希望将类型错误传播到函数边界之外。

或者,您可能希望更深入地匹配并且 select 仅某些声明:

void foo(class("MyClass", str _, str _, list[Decl] _)) { ... }

或者,匹配所有 class 具有 equals 方法的嵌套深度匹配:

void foo(class(str name, str _, str _, /method("equals",_,_)) {  ... }

Rascal 函数定义的本质是它们可以重载,并且分派是基于模式匹配动态完成的。作为程序员,您需要使模式互斥,或者如果这不可能,您可以使用 default 修饰符来强制进行部分排序。

例如,这是非法的,因为模式 0int n 重叠:

int f(0) = 1;
int f(int n) = f(n - 1) * n;

不过你可以这样写:

int f(0) = 1;
default f(int n) = f(n - 1) * n;

除了互斥之外,重载函数也需要完整。 这意味着对于您的 class 案例,您将需要为您不匹配的其他案例提供默认定义:

default void foo(Decl d) {
  throw "did not implement foo for <d>";
}

可在此处找到更多信息: