我一直在尝试为我想从我的项目中引用的开源项目生成 SBT 构建,但我遇到了似乎是编译器错误的问题。
以下代码在 eclipse/scala-ide 中按预期编译和运行,但 scala 2.10.6 编译器无法消化它:
package foo
import scala.language.dynamics
object Caller extends App {
val client = new Client() // initialise an R interpreter
client.x = 1.0
}
class Client extends Dynamic {
var map = Map.empty[String, Any]
def selectDynamic(name: String) = map get name getOrElse sys.error("field not found")
def updateDynamic(name: String)(value: Any) { map += name -> value }
}
这是我的 build.sbt:
scalaVersion := "2.10.6"
libraryDependencies++= Seq(
"org.scalanlp" %% "breeze" % "0.12"
)
当我指定 scalaVersion := 2.10.6 时,我收到以下编译错误:
[error] /home/philwalk/dynsbt/src/main/scala/foo/Caller.scala:8: type mismatch;
[error] found : foo.Caller.client.type (with underlying type foo.Client)
[error] required: ?{def x: ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error] both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
[error] and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
[error] are possible conversion functions from foo.Caller.client.type to ?{def x: ?}
[error] client.x = Seq("a","b","c")
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 3 s, completed May 3, 2016 11:03:08 AM
使用 scalaVersion := 2.11.8,没有问题,尽管我需要交叉编译,所以这不是解决方法。
另一个线索是我可以通过更改这行代码来隐藏问题:
client.x = 1.0
对此:
client.xx = 1.0
当我直接用 scalac 2.10.6 编译时,我也看到了这个问题。
作为一种解决方法,我可以重构项目以使用比单个字符更长的字段名称,尽管因为它不是我的项目,我在某种程度上受限于我可以接受的解决方法。此外,它是一个breeze.linalg 项目,禁止使用单个字符矩阵和向量名称将是一个严重的限制。
花了几个小时将问题归结为来自一个更大项目的代码片段,我不希望对这个开源库的 scala 2.10 版本施加限制。由于此错误似乎已在 scala 2.11 中修复,我假设已决定不将该修复程序向后移植到 2.10。
我更改了标题以反映解决方法的存在(更长的字段名称)。