简体   繁体   English

Scala中的隐式冲突

[英]Collision of implicits in Scala

The following Scala code works correctly: 以下Scala代码可正常运行:

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 然后Scala(2.10)编译器显示错误: 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 . 看来stringToNode的存在以某种方式阻止了str1str2WrappedString的隐式转换。 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 ? 并且有一种方法可以修改stringToNode ,使zip起作用,但是当我调用需要带有StringNode参数的函数时仍使用stringToNode吗?

You have ambiguous implicits here. 您在这里有含糊的隐式。 Both StringOps and xml.Node have the zip-method, therefore the implicit conversion is ambiguous and cannot be resolved. StringOps和xml.Node都具有zip方法,因此隐式转换是模棱两可的,无法解决。 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 以下是一些支持备份的链接: http : //www.scala-lang.org/api/current/index.html#scala.collection.immutable.StringOpshttp://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. 编辑 :是StringOps,而不是WrappedString,更改了链接:)看一下Predef: http : //www.scala-lang.org/api/current/index.html#scala.Predef $在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 ). 您需要2个不同的隐式转换,它们都提供相同名称的方法( 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. 另外,如果导入xml.Text,则可以仅使用Text(str)进行转换,这对于任何人都应该足够简洁。 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. 如果您必须将此隐式转换为xml.Node,我会将隐式def打包到一个对象中,然后仅在需要它的地方将其导入,以使代码可读,并尽可能避免在您也需要冲突的地方进行导入邮编。 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. 就像@Felix所写的一样,在类似的数据类型之间定义隐式转换通常是个坏主意,就像您所使用的那样。 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. Scala中的隐式转换通常用于定义轻量级,短暂的包装器,以丰富包装类型的API。 Implicit conversion that converts String into WrappedString falls into that category. String转换为WrappedString隐式转换属于该类别。

Twitter's Effective Scala has a section about this issue. Twitter的有效Scala中有关于此问题的部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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