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

时间:2015-03-19 17:42:48

标签: pattern-matching rascal

我想知道是否可以指定作为参数传递给函数的节点的确切构造函数。例如,如果在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内部进行匹配来获取类节点的部分内容。

或者,是否有一种不同且更有效的方法。

谢谢!

1 个答案:

答案 0 :(得分:2)

当然,而且你可以将完整的模式匹配作为参数,你不一定要提到完整的路径:

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

或将e绑定到完整的类声明:

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

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

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

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

或者,嵌套的深匹配匹配所有具有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;

在互斥的旁边,重载的功能也需要完成。 这意味着对于您的类案例,您将需要一个您不匹配的其他案例的默认定义:

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

可在此处找到更多信息: