我想知道是否可以指定作为参数传递给函数的节点的确切构造函数。例如,如果在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内部进行匹配来获取类节点的部分内容。
或者,是否有一种不同且更有效的方法。
谢谢!
答案 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
修饰符强制进行部分排序。
例如,这是非法的,因为模式0
与int 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>";
}
可在此处找到更多信息: