【问题标题】:map over structure with only partial match仅部分匹配的结构映射
【发布时间】:2011-04-01 17:35:06
【问题描述】:

我有一个抽象类和案例类的树状结构,代表一种小语言的抽象语法树。

对于顶级抽象类,我实现了一个方法map

abstract class AST {
...
  def map(f: (AST => AST)): AST = {
     val b1 =  this match {
      case s: STRUCTURAL => s.smap(f) // structural node for example IF(expr,truebranch,falsebranch)
      case _ => this // leaf, // leaf, like ASSIGN(x,2)
    }
    f(b1)
  }
...

smap 的定义如下:

 override def smap(f: AST => AST) = {
    this.copy(trueb = trueb.map(f), falseb = falseb.map(f))
  }

现在我正在编写不同的“转换”来插入、删除和更改 AST 中的节点。

例如,从块中删除相邻的 NOP 节点:

def handle_list(l:List[AST]) = l match {
  case (NOP::NOP::tl) => handle_list(tl)
  case h::tl => h::handle_list(tl)
  case Nil => Nil
}

ast.map {
  case BLOCK(listofstatements) => handle_list(listofstatements)
}

如果我这样写,我最终会得到MatchError,我可以通过将上面的映射更改为:

ast.map {
  case BLOCK(listofstatements) => handle_list(listofstatements)
  case a => a
}

我应该只接受所有这些case a => a,还是可以以某种方式改进我的map 方法(或其他部分)?

【问题讨论】:

    标签: scala functional-programming map


    【解决方案1】:

    map 的参数设为PartialFunction

    def map(f: PartialFunction[AST, AST]): AST = {
      val idAST: PartialFunction[AST, AST] = {case a => a}
      val g = f.orElse(idAST)
    
      val b1 =  this match {
        case s: STRUCTURAL => s.smap(g)
        case _ => this
      }
      g(b1)
    }
    

    【讨论】:

    • 哇!我不断地在 Scala 中看到奇妙的东西。这正是我想要的
    • 该代码可能有点错误,因为我没有注意到f 被用作smap 的参数。固定。
    • 不是orElse 而不是andThen
    • 当然可以(它需要PartialFunction 而不仅仅是Function 才能启动,所以我需要更多类型注释才能使其工作)。
    【解决方案2】:

    如果树转换不仅仅是您项目的一个次要方面,我强烈建议您使用Kiama 的重写器模块来实现它们。它实现了类似 Stratego 的战略驱动转换。它有一组非常丰富的策略和策略组合器,允许将遍历逻辑(在绝大多数情况下可以从提供的策略和组合器中“现成”)与(本地)转换(它们是特定于您的 AST 并且您提供,当然)。

    【讨论】:

    • 非常有趣。会调查的!
    猜你喜欢
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多