How to use star pattern with unapplySeq in Scala?

Viewed 106

I implemented simple unapplySeq that extracts elements of filepath to sequence:

object PathSequence {
  def unapplySeq(path: Path): Seq[String] =
    if (path == null || path.getFileName == null) Seq.empty
    else path.getFileName.toString +: unapplySeq(path.getParent)
}

After runing it like this:

val path = Path.of("C:/Users/WIN10/IdeaProjects/LearningSandbox/src/worksheet/resources/AddTwoNumbers.java")
val PathSequence(first, second, third, _*) = path

I get an error: Star pattern must correspond with varargs or unapplySeq.

unapplySeq is implemented correctly here, the result is List(AddTwoNumbers.java, resources, worksheet, src, LearningSandbox, IdeaProjects, WIN10, Users)

How to set first, second and third variables to first three elements of result sequence?

1 Answers

Apparently the problem is that unapplySeq also has to return an Option[Seq[A]].

However, if you are sure that you will always match you can return a Some[Seq[A]].
Check this:

object PathSequence {
  @annotation.tailrec
  private def loop(remaining: Option[Path], acc: List[String]): List[String] =
    remaining match {
      case Some(path) =>
        Option(path.getFileName) match {
          case Some(file) =>
            loop(remaining = Option(path.getParent), file.toString :: acc)
          
          case None =>
            List.empty
        }
      
      case None =>
        acc.reverse
    }
  
  def unapplySeq(path: Path): Some[List[String]] =
    Some(loop(remaining = Option(path), acc = List.empty))
}

Which you can see how it working here.

Related