映射结构只有部分匹配

时间:2010-08-20 15:24:41

标签: scala functional-programming map

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

对于顶级抽象类,我实现了一个方法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方法(或其他部分)?

2 个答案:

答案 0 :(得分:4)

如果树转换不仅仅是项目的一个次要方面,我强烈建议您使用Kiama的重写器模块来实现它们。它实现了类似Stratego的策略驱动的转换。它有一套非常丰富的策略和策略组合器,允许完全分离遍历逻辑(对于绝大多数情况,可以从提供的策略和组合器中“从现有的”获取)来自(本地)转换(这是特别是你的AST和你提供的,当然)。

答案 1 :(得分:4)

将参数设为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)
}