Germán Bouzas
Germán Bouzas

Reputation: 1480

scala match on iteration, weird compiler error

This small piece of scala code when compiled it gives a strange error.

import scala.collection.mutable.ListBuffer

object main {
  def main(args: Array[String]) {

    val rs = new ListBuffer[String]()
    val ns = scala.collection.mutable.Map[String, String]()

    "A very long string".split("\\ ") foreach { word =>

        word match {
            case x if x.length() > 7  => ns += x -> "="
            case _ =>   rs += word 
        }
    }
  }
}

Gives the following error:

test.scala:11: error: type arguments [String,Iterable[java.io.Serializable] with PartialFunction[String with Int,String] with scala.collection.generic.Subtractable[String,Iterable[java.io.Serializable] with PartialFunction[String with Int,String] with scala.collection.generic.Subtractable[String,Equals]]{def seq: Iterable[java.io.Serializable] with PartialFunction[String with Int,String]}] do not conform to trait Subtractable's type parameter bounds [A,+Repr <: scala.collection.generic.Subtractable[A,Repr]]
    "A very long string".split("\\ ") foreach { word =>
                                              ^
one error found

Any hints?

Upvotes: 2

Views: 493

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

This happens due to the fact that your pattern match returns a lengthy compound type:

[String,Iterable[java.io.Serializable] with PartialFunction[String with Int,String] with scala.collection.generic.Subtractable[String,Iterable[java.io.Serializable] with PartialFunction[String with Int,String] with scala.collection.generic.Subtractable[String,Equals]]{def seq: Iterable[java.io.Serializable] with PartialFunction[String with Int,String]}]

Where one of the types in the linearization is Subtractable[String, Iterable[Serializable]] which your type doesn't conform to it's type constraint:

trait Subtractable[A, +Repr <: Subtractable[A, Repr]

To fix this, help the compiler out with type annotation on foreach:

"A very long string"
  .split("\\")
  .foreach[Unit] {
  case x if x.length() > 7 => ns += x -> "="
  case word => rs += word
}

As a side note, perhaps you can find the following implementation helpful:

val (largerThanSeven, smallerThanSeven) = "A very long string"
  .split("\\")
  .partition(_.length > 7)

val largerThanSevenMap = largerThanSeven.map(_ -> "=").toMap

Upvotes: 1

Antot
Antot

Reputation: 3964

The problem is here:

ns += x -> "="

I guess the intention is to put the key x and the value "=" into the mutable map.

This will compile if changed to

ns(x) = "="

The problem is that there are implicits involved into conversions with -> and the types are inferred weirdly into the monstrous string in the error message.

Upvotes: 1

Related Questions