简体   繁体   中英

Collision of implicits in Scala

The following Scala code works correctly:

val str1 = "hallo"
val str2 = "huhu"
val zipped: IndexedSeq[(Char, Char)] = str1.zip(str2)

However if I import the implicit method

implicit def stringToNode(str: String): xml.Node = new xml.Text(str)

then the Scala (2.10) compiler shows an error: value zip is not a member of String

It seems that the presence of stringToNode somehow blocks the implicit conversion of str1 and str2 to WrappedString . Why? And is there a way to modify stringToNode such that zip works but stringToNode is still used when I call a function that requires a Node argument with a String ?

You have ambiguous implicits here. Both StringOps and xml.Node have the zip-method, therefore the implicit conversion is ambiguous and cannot be resolved. I don't know why it doesn't give a better error message.

Here are some links to back it up: http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.StringOps and http://www.scala-lang.org/api/current/index.html#scala.xml.Node

edit : it was StringOps, not WrappedString, changed the links :) Have a look at Predef: http://www.scala-lang.org/api/current/index.html#scala.Predef $ to see predefined implicits in Scala.

I would avoid using implicits in this case. You want 2 different implicit conversions which both provide a method of the same name ( zip ). I don't think this is possible. Also, if you import xml.Text, you can convert with just Text(str) which should be concise enough for anyone. If you must have this implicit conversion to xml.Node, I would pack the implicit def into an object and then import it only in the places where you need it to make your code readable and to, possibly, avoid conflicts where you also need to zip strings. But basically, I would very much avoid using implicits just to make convenient conversions.

Like @Felix wrote, it is generally a bad idea to define implicit conversions between similar data types, like the one you used. Doing that weakens type system, leads to ambiguities like you encountered and may produce extremely unclear ("magic") code which is very hard to analyze and debug.

Implicit conversions in Scala are mostly used to define lightweight, short-lived wrappers in order to enrich API of wrapped type. Implicit conversion that converts String into WrappedString falls into that category.

Twitter's Effective Scala has a section about this issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM