Scala 匹配递归对象

问题描述

我是 Scala 的新手,我想构建一个与对象匹配的小型递归模式。 我在以下代码中不断收到不匹配:

abstract class Fixednode

case class LoopBeginNode(lb: ArrayLengthNode) extends Fixednode  
case class ArrayLengthNode(al: Fixednode) extends Fixednode  
case class IfNode(i: Fixednode) extends Fixednode
case class BeginNode(b: Fixednode) extends Fixednode
case class Loadindexednode(li: Fixednode) extends Fixednode
case class FixedGuardNode(fg: Fixednode) extends Fixednode
case class EndNode(e: String) extends Fixednode

object HelloWorld {
    
    def main(args: Array[String]) {
      println(matchIt(LoopBeginNode(ArrayLengthNode(EndNode("")))))
    }
    
    def matchIt(e: Fixednode): String = e match {
      case EndNode(en) => "match"
      case LoopBeginNode(lb) if lb == ArrayLengthNode(e) => matchIt(lb)
      case ArrayLengthNode(al) if al == EndNode("") => matchIt(al)
      case IfNode(i) if i == BeginNode(i) => matchIt(i)
      case BeginNode(b) if b == EndNode("") =>matchIt(b)
      case _ => "No match"
    }
   }

如果我添加一个简单的 LoopBeginNode(EndNode("")),我会得到一个匹配项。虽然在上面更复杂的情况下,我得到了一个不匹配,根据我的理解,它来自 lb 变量,它是一个 EndNode 而在条件中是一个 Fixednode。你知道我将如何使它工作吗? 最后我想以更复杂的方式结束

ArrayLengthNode(IfNode(BeginNode(Loadindexednode(GuardeElseNode(LoadindexNode(IfNode(EndNode(""))))))))

解决方法

您的模式匹配结构不太正确,请在下面找到更正的:

/**
* Use `sealed` to box type and pattern matching will show compilation warnings.
*/
sealed trait FixedNode

case class LoopBeginNode(lb: ArrayLengthNode) extends FixedNode  
case class ArrayLengthNode(al: FixedNode) extends FixedNode  
case class IfNode(i: FixedNode) extends FixedNode
case class BeginNode(b: FixedNode) extends FixedNode
case class LoadIndexedNode(li: FixedNode) extends FixedNode
case class FixedGuardNode(fg: FixedNode) extends FixedNode
case class EndNode(e: String) extends FixedNode

object HelloWorld {
    
    def main(args: Array[String]) {
      println(matchIt(LoopBeginNode(ArrayLengthNode(EndNode("")))))
      
      //ArrayLengthNode(IfNode(BeginNode(LoadIndexedNode(GuardeElseNode(LoadIndexNode(IfNode(EndNode(""))))))))
    }
    
    def matchIt(e: FixedNode): String = e match {
      case EndNode(en) => "match"
      /**
       * In previous version `case LoopBeginNode(lb) if lb == ArrayLengthNode(e) => matchIt(lb)`
       * 'lb == ArrayLengthNode(e)' - always false,because you comparing in this case 
       * `ArrayLengthNode(EndNode("")) == ArrayLengthNode(LoopBeginNode(ArrayLengthNode(EndNode(""))))`
       * which is always false.
       *
       * Same approach used for other patterns
       */
      case LoopBeginNode(ArrayLengthNode(lb)) => matchIt(lb)
      case ArrayLengthNode(EndNode("")) => "match"
      case IfNode(BeginNode(i)) => matchIt(i)
      case BeginNode(EndNode("")) => "match"
      case _ => s"No match at: `$e`"
    }
}

和 Scatie 一起玩:https://scastie.scala-lang.org/zfEd5DprQUKDttLcc6D54w