この質問に答える前に、まず Scala のバージョンを修正して、質問を再現できるようにしましょう。Scala 2.11.8、sbt 0.13.11、spire-math 0.11.0 を使用していると仮定しましょう。
次に、生の build.sbt は次のようになります。
name := "test"
version := "1.0"
scalaVersion := "2.11.8"
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
libraryDependencies += "org.spire-math" %% "spire" % "0.11.0"
コードは次のようにTest.scala
ファイルに保存できます。
import spire.implicits._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
object Test {
def main(args: Array[String]) = {
val toolBox = currentMirror.mkToolBox()
val src ="""
|(a: spire.math.Jet[Double],b: spire.math.Jet[Double]) => a + b
""".stripMargin
println (toolBox.eval(toolBox.parse(src)))
}
}
を実行するsbt run
と、次の情報が得られます。
$ sbt run
[info] Running Test
[error] scala.tools.reflect.ToolBoxError: reflective compilation has failed:
[error] could not find implicit value for parameter f: spire.algebra.Field[Double]
したがって、あなたの質問は、で定義された暗黙がインスタンス化されて呼び出されるimport spire.implicits._
スコープに含まれているにもかかわらず、なぜこれが失敗するのかということです。toolBox
eval
さて、あなたのユース ケースでは、コンパイラが個別に呼び出される 2 つの段階があることに注意してください。第 1 段階は のコンパイルでTest.scala
、第 2 段階は のコンパイルと実行です。(a: spire.math.Jet[Double],b: spire.math.Jet[Double]) => a + b
この 2 つのステージは、同じランタイムでは動作しません。最初の段階ではコンパイラが呼び出されてTest.scala
ファイルがコンパイルされ、2 番目の段階では JVM ランタイム内で呼び出されてsrc
文字列がコンパイルされます。結果として、これら 2 つのステージは、異なるランタイムで実行されるという理由だけで、同じスコープを共有しません。
この問題の簡単な解決策の 1 つは、第 2 段階のスコープで暗黙を「再導入」することです。つまりimport spire.implicits._
、コンパイルしようとする文字列の先頭に追加します。
import spire.implicits._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
object Test {
def main(args: Array[String]) = {
val toolBox = currentMirror.mkToolBox()
val src ="""
|import spire.implicits._
|(a: spire.math.Jet[Double],b: spire.math.Jet[Double]) => a + b
""".stripMargin
println (toolBox.eval(toolBox.parse(src)))
}
}
その結果:
$ sbt run
[info] Running Test
<function2>
[success] Total time: 5 s, completed Jul 13, 2016 1:48:59 AM
これがあなたの質問に答えることを願っています。Scala コンパイラがどのようにスコープ内の暗黙を検索しているかについての詳細な回答が必要な場合は、ここから始めるのがよいでしょう。