2

I am trying to define a binary tree with the following definition:

  trait Node {
    val label: Int
  }
  case class BranchNode(override val label: Int, left: Option[Node], right: Option[Node]) extends Node
  case class LeafNode(override val label: Int) extends Node

and then define a simple printTree method using Scala's pattern matching as below:

  def printTree(aTree: Option[Node]): Unit = aTree match {
    case None => print(".")
    case Some(LeafNode(label)) => print(label)
    case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
  }

The Intellij IDE warns me that the match may not be exhaustive. An Option can have None or Some as it's values. In case of Option[Node], it can either be Some(LeafNode) or Some(BranchNode). What other cases am I overlooking?

2 Answers 2

6

Since your trait isn't sealed, it is open for extension in different packages. IntelliJ is warning you of the future possibility that anyone extending this trait and forgetting to implement an additional case may cause a MatchError. If you want to limit it's extension, use:

sealed trait Node
Sign up to request clarification or add additional context in comments.

Comments

3

Definitely its a compiler warning, see below I'm breaking your code, by passing printTree(Option(IWillBreakYou(2)))

match error

      trait Node {
        val label: Int
      }
      case class BranchNode(override val label: Int, left: Option[Node], right: Option[Node]) extends Node
      case class LeafNode(override val label: Int) extends Node

      case class IWillBreakYou(override val label: Int) extends Node

      def printTree(aTree: Option[Node]): Unit = aTree match {
        case None => print(".")
        case Some(LeafNode(label)) => print(label)
        case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
      }

      val leftNode = Option(LeafNode(2))
      val rightNode = Option(LeafNode(3))
      printTree(Option(BranchNode(1, leftNode, rightNode)))

      printTree(Option(IWillBreakYou(2))) //this will fail

The reason is since you are taking Option[Node] AND anybody can extend Node (within/outside of package unless protected) which you are not considering in your matches.

So, adding failsafe match case _ would fix the future error.

def printTree(aTree: Option[Node]): Unit = aTree match {
        case None => print(".")
        case Some(LeafNode(label)) => print(label)
        case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
        case _ => println("do nothing")
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.