2012-08-25 5 views

답변

52

컴파일 도구 상자는 식 = 반환 값만을 실행할 수 있지만 컴파일 결과가 포함 된 결과 클래스 또는 파일/바이트 배열은 실행할 수 없습니다.

그러나 그것은 스칼라에서 암시 적 값을 사용하여 값 수준으로 타입 수준에서 갈 너무 쉽게이기 때문에, 당신이 원하는 것을 달성하기 위해 여전히 가능 :

편집. 2.10.0-RC1에서는 ToolBox의 몇 가지 메서드가 변경되었습니다. parseExpr은 이제 parse이며, runExpr은 이제 eval입니다.

scala> import scala.reflect.runtime._ // requires scala-reflect.jar 
             // in REPL it's implicitly added 
             // to the classpath 
             // but in your programs 
             // you need to do this on your own 
import scala.reflect.runtime 

scala> val cm = universe.runtimeMirror(getClass.getClassLoader) 
cm @ 41d0fe80: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader... 

scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar 
              // in REPL it's implicitly added 
              // to the classpath 
              // but in your programs 
              // you need to do this on your own 
import scala.tools.reflect.ToolBox 

scala> val tb = cm.mkToolBox() 
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = [email protected] 

scala> tb.runExpr(tb.parseExpr("class C; scala.reflect.classTag[C].runtimeClass")) 
res2: Any = class __wrapper$1$f9d572ca0d884bca9333e251c64e980d$C$1 

업데이트 # 1. java.lang.Class가 필요없고 컴파일 된 클래스를 인스턴스화하기 만하면 runExpr에 제출 된 문자열에 new C을 직접 쓸 수 있습니다.

업데이트 # 2. runExpr에 변수 이름에서 런타임 값까지의 사용자 지정 매핑을 사용할 수도 있습니다. 예를 들어 :

scala> val build = scala.reflect.runtime.universe.build 
build: reflect.runtime.universe.BuildApi = [email protected] 

scala> val x = build.setTypeSignature(build.newFreeTerm("x", 2), typeOf[Int]) 
x: reflect.runtime.universe.FreeTermSymbol = free term x 

scala> tb.runExpr(Apply(Select(Ident(x), newTermName("$plus")), List(Literal(Constant(2))))) 
res0: Any = 4 

이 예에서 I 2의 값이 무료로 용어를 생성 (값이 원시적 될 필요가 없습니다 - 그것은 사용자 정의 객체가 될 수 있습니다)과에 식별자를 바인딩합니다. 이 값은 도구 상자에서 컴파일되고 실행되는 코드에서 그대로 사용됩니다.

이 예제에서는 수동 AST 어셈블리를 사용하지만 문자열을 구문 분석하고 언 바운드 식별자를 찾아서 일부 매핑에서 값을 찾아 해당 자유 용어를 만드는 함수를 작성할 수 있습니다. Scala 2.10.0에는 그런 기능이 없습니다.

+0

감사합니다. 하나의 후속 조치 : Scala의 리플렉션으로 java.lang.Class가 반환 된 핸들을 얻을 수있는 방법이 있습니까? 아니면 오래된 자바 하나만 사용해야할까요? –

+2

예. ' .classSymbol ()'를 사용하십시오. 여기서 ='scala.reflect.runtime.universe.runtimeMirror ( .getClassLoader의 인스턴스)'. 그런 다음 스칼라 리플렉션 기호를 얻습니다. 스칼라 리플렉션 기호는 스칼라 리플렉션 API로 검사 할 수 있습니다. –

+0

왜 classOf [C] 대신에'reflect.runtime.currentMirror'와'scala.reflect.classTag [C] .runtimeClass' 대신'universe.runtimeMirror (getClass.getClassLoader)'를 사용 했습니까? 그것은 내 일에 잘 작동하는 것으로 판명되었다. 도와 주셔서 감사합니다, btw! –

관련 문제