Raxkin
Raxkin

Reputation: 397

Implicit Map makes Char methods not compile

So with this code the head and exists methods are not returning a Char but a String so i can't use any Char method.

implicit val mapTest: Map[String, Set[String]] = Map(
    "foo" -> Set("foo")
  )
  val stringTest: String = "test"

  //This don't compile
  stringTest.head.isLetter
  stringTest.exists(_.isLetter)

If i remove the implicit, it works fine. It works fine if i change the Map definition to Map[String, String], but using any Collection in the map makes is not compile.

Is there a way to make it work? I also tried defining the Char type after calling head but it still fails

Upvotes: 1

Views: 39

Answers (2)

Mario Galic
Mario Galic

Reputation: 48420

Implicit conversions may lead to seemingly magical changes to semantics of the code and loss of control by the developer, which your example nicely demonstrates. For this reason they are often discouraged and we are advised to find ways to refactor the code to not use them if at all possible.

If there is no way around it, consider moving the implicit conversion "out-of-scope" by wrapping it in another object like so

object FooImplicits {
  implicit def mapTest: Map[String, Set[String]] = Map(
    "foo" -> Set("foo")
  )
}

and then try to avoid importing them at the top level, but instead import FooImplicits._ only where it is absolutely necessary.

Note that implicits are acceptable when defining typeclasses and extension methods.

Upvotes: 1

cchantep
cchantep

Reputation: 9168

Don't expose mapTest in implicit scope: as it offers .apply(key: String): Set[String] it's considered as an implicit conversion String => Set[String] .

Anyway implicit conversion should be defined/used with caution, due to readability drawbacks.

Using .head (or .get) is a code smell.

Upvotes: 2

Related Questions