2016-04-19 8 views
2

die Scala verwenden (Runtime) relection API, ich versuche, den Code zu kompilieren, die starke Nutzung von implicits (eigentlich die spire.math Bibliothek) macht:Wie man implicits zur Reflexion zur Verfügung

val src = "(a: spire.math.Jet[Double],b: spire.math.Jet[Double]) => a + b" 
    println(toolBox.eval(toolBox.parse(src))) 

Obwohl diese implicits im Rahmen sichtbar sind, in denen toolbox.eval genannt wird, reflektierende Kompilation immer noch nicht:

could not find implicit value for parameter f: spire.algebra.Field[Double] 

Wie kann ich diese Informationen machen auf die ToolBox zur Verfügung?

+0

Was ist das Ziel? – cchantep

+0

@cchanstep - Bearbeitet, um zu klären. – NietzscheanAI

Antwort

3

Bevor wir diese Frage beantworten, müssen wir zuerst die Scala-Version reparieren und Ihre Frage reproduzierbar machen. Nehmen wir an, wir verwenden Scala 2.11.8, sbt 0.13.11 und spire-math 0.11.0.

Dann wird die blanke build.sbt könnte die aussehen wie folgt:

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" 

und der Code kann in Test.scala Datei gespeichert werden, die aussehen wie:

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))) 
    } 
} 

Nach sbt run Ausführung, erhalten Sie:

$ 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] 

So ist Ihre Frage, warum tut t sein Fehlschlag, obwohl die in import spire.implicits._ definierten Implikationen in dem Bereich enthalten sind, in dem toolBox instanziiert ist und eval aufgerufen wird.

Nun, beachten Sie, dass Sie in Ihrem Anwendungsfall zwei Stufen haben, in denen der Compiler unabhängig aufgerufen wird. Die erste Stufe ist die Kompilation Test.scala und die zweite Stufe ist die Kompilierung und Ausführung von (a: spire.math.Jet[Double],b: spire.math.Jet[Double]) => a + b

Diese zwei Stufen arbeiten nicht in der gleichen Laufzeit. In der ersten Phase wird der Compiler aufgerufen, um die Datei Test.scala zu kompilieren, und in der zweiten wird er innerhalb der JVM-Laufzeit aufgerufen, um die Zeichenfolge src zu kompilieren. Daher haben diese beiden Stufen nicht den gleichen Umfang, weil sie in unterschiedlichen Laufzeiten ausgeführt werden.

Eine schnelle Lösung für dieses Problem ist die "Wiedereinführung" der Implikationen im Rahmen der zweiten Stufe. Mit anderen Worten prepend Sie import spire.implicits._ in der Zeichenfolge, die Sie versuchen, zu kompilieren:

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))) 
    } 
} 

, die zu den Ergebnissen:

$ sbt run 
[info] Running Test 
<function2> 
[success] Total time: 5 s, completed Jul 13, 2016 1:48:59 AM 

Hoffnung dies Ihre Frage beantwortet. Wenn Sie eine gründliche Antwort darauf möchten, wie der Scala-Compiler nach Implikationen in den Bereichen sucht, wäre ein guter Start here.

Verwandte Themen