2013-08-28 26 views
1

我已經在scala lang論壇發佈了這個問題,但不幸的是我沒有得到任何答案。 第二次機會?在Scala中解釋器中綁定實例時的類路徑問題

我嘗試在此解釋器中嵌入解釋器並評估scala片段。我想在解釋器中綁定一個自定義類的實例。綜上所述,將是這樣的:

import scala.tools.nsc._ 
import scala.tools.nsc.interpreter._ 

class C { 
    def sayHello(s:String) = "hello "+s 
} 

object Main extends App { 

val c= new C 

val s = new Settings 
s.usejavacp.value=true 

val i = new IMain(s) 
i.bind("myC",c) 
i.bind("world","the world") 

val script = "println(myC.sayHello(world))" 
i.eval(script) 

}

當我運行Eclipse(開普勒)這裏面的片斷 - OpenJDK6/7適用於這兩種 - BSD操作系統斯卡拉-2.11.0-M4 - scala- compiler.jar在它工作的路徑很好 如果我嘗試在repl中運行相同的代碼或直接使用scalac file.scala然後scala -cp。主要我收到以下錯誤

error: not found value myC 
    javax.script.ScriptException: compile-time error 
    at scala.tools.nsc.interpreter.IMain.compile(IMain.scala:575) 
    at scala.tools.nsc.interpreter.IMain.eval(IMain.scala:997) 
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) 

我能夠讓它在另一個操作系統(Win7的),但通過添加s.bootclasspath工作=「路徑/要/我的/班」

我懷疑一些類路徑問題

後來我能夠使其通過Java調用替換斯卡拉命令行調用這種方式運行: java -cp $CLASSPATH Main與它的工作原理

我看着斯卡拉命令包含CLASSPATH的Scala庫,它是喜歡它澳鵬以不同的方式在java路徑中的ds scala庫。

有沒有人有任何建議?

感謝

基於以下意見

補充:

Scalac不輸出任何錯誤 事實上,如果我運行:

java -cp .:$SCALA_PATH/lib/scala-library.jar:$SCALA_PATH/lib/scala-compiler.jar:$SCALA_PATH/lib/scala-reflect.jar Main 

或建議斯卡拉-nobootcp它的工作原理(謝謝有價值的意見) 否則,如果我讓scala使用bootcp,啓動的行是下面的一個,它會失敗

java -Xbootclasspath/a:/usr/home/pcohen/Dev/Scala/scala-2.11.0-M4/lib/akka-actors.jar[...] -classpath "" [...] 

當scala jar添加到bootclasspath時,它就像我的綁定失敗。我無法清楚地理解爲什麼這個bootclasspath差異會影響我的類。

+1

你能證明收到這個錯誤時,您正在使用的scalac命令? – AlexBrand

回答

3

我不知道這是否有資格作爲建議,但你是否知道:

scala> class C { def sayHello(s: String) = s"hello, $s" } 
defined class C 

scala> $intp.bind("world","the world") 
world: String = the world 
res0: scala.tools.nsc.interpreter.IR.Result = Success 

scala> val c = new C 
c: C = [email protected] 

scala> $intp interpret "c sayHello world" 
res2: String = hello, the world 
res1: scala.tools.nsc.interpreter.IR.Result = Success 

設有獨立的編譯,你的例子使用scala -nobootcp my.Main

您可以通過-Dscala.repl.debug=true查看更多信息。你會看到從bindError回報(大家檢查結果值,右println(i.bind("myC",c))?)引起的:

java.lang.ClassCastException: intpbind.C cannot be cast to intpbind.C

並試圖它的包裝代碼。

更多的話:

你說,「它就像我的綁定失敗」,但正如我上面顯示,它正是綁定失敗。

原因是,當你說「綁定」時,你的意思是「自動生成一些代碼,就像我寫的一樣,scala> val myC = c」。呵呵,編譯它,然後讓myC這個符號可以被REPL會話的其餘部分導入。

當您使用引導類路徑上的REPL編譯該代碼時,引導類路徑必須能夠看到您的類C。 (它也必須是你的應用程序類加載器加載主類中的一個加載的同一類;憑藉代表團通常是真實的。)

所以,這個工程:

scalac -d /tmp/out mytest.scala 
scala -J-Xbootclasspath/a:/tmp/out mytest.Test 

你可能會使你的一些類只放在引導類路徑上,或者,更可能的是,你會按我的建議去做,並從引導類路徑中取消scala。 。

我還沒有研究這一點,但你可以谷歌的人使用嵌入在託管環境中的REPL它真的很重要,你住在什麼樣的類加載器類似的問題

獎金效用:

package scala { 
    package object foo { 
    def show(cl: ClassLoader): String = scala.reflect.runtime.ReflectionUtils.show(cl) 
    } 
} 

使用的只是傾銷您所感興趣的類加載器斯卡拉 - 私營公用事業:

import scala.foo._ 
    Console println show(getClass.getClassLoader) 
+0

他們需要降低投入成本;或者至少匿名的不贊成對話的讚譽應該有一個真實的成本。首先,這是一個毫無意義的分心。 –