【问题标题】:Use pattern matching in function parameters在函数参数中使用模式匹配
【发布时间】:2015-03-20 18:07:47
【问题描述】:

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

或者,有没有其他更有效的方法来做到这一点。

谢谢!

【问题讨论】:

    标签: pattern-matching rascal


    【解决方案1】:

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

    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>";
    }
    

    更多信息可以在这里找到:

    【讨论】:

    • 太棒了!非常感谢。尽管您如何在函数定义中使用Decl,但我有点困惑。 [编辑:哦,我认为您的意思是类构造函数的完整路径]。
    • 是的,很抱歉造成混乱。我正是这个意思。仅当 datasyntax 名称发生冲突时才需要限定名称。
    猜你喜欢
    • 1970-01-01
    • 2012-09-02
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多