2012-08-25 35 views

Trả lời

52

W.r.t hộp công cụ biên dịch chỉ có thể chạy biểu thức = giá trị trả về, nhưng không thể tạo các lớp hoặc tệp/mảng byte với kết quả biên dịch.

Tuy nhiên nó vẫn có thể đạt được những gì bạn muốn, vì trong Scala nó rất dễ dàng để đi từ cấp loại mức giá trị sử dụng giá trị tiềm ẩn:

Sửa. Trong 2,10.0-RC1 một số phương pháp của ToolBox đã được đổi tên. parseExpr hiện chỉ là parserunExpr hiện được gọi là 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 

Cập nhật # 1. Nếu bạn không cần java.lang.Class và chỉ cần khởi tạo lớp đã biên dịch, bạn có thể viết trực tiếp new C trong chuỗi được gửi đến runExpr.

Cập nhật # 2. Cũng có thể có runExpr sử dụng ánh xạ tùy chỉnh từ tên biến đến giá trị thời gian chạy. Ví dụ:

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 

Trong ví dụ này tôi tạo điều khoản miễn phí có giá trị 2 (giá trị không phải là một nguyên thủy - nó có thể là đối tượng tùy chỉnh của bạn) và ràng buộc một định danh với nó. Giá trị này sau đó được sử dụng như là trong mã được biên soạn và chạy bởi một hộp công cụ.

Ví dụ sử dụng lắp ráp thủ công AST, nhưng có thể viết một hàm phân tích chuỗi, tìm ra số nhận dạng không liên kết, tra cứu giá trị cho chúng trong một số ánh xạ và sau đó tạo các thuật ngữ miễn phí tương ứng. Không có chức năng như vậy trong Scala 2.10.0 mặc dù.

+0

Cảm ơn! Một theo dõi: có cách nào để tôi có được một xử lý trên này trở lại 'java.lang.Class' với sự phản ánh của Scala hoặc tôi sẽ chỉ phải dính vào đồng bằng cũ của Java? –

+2

Chắc chắn. Sử dụng ' .classSymbol ()', trong đó = 'scala.reflect.runtime.universe.runtimeMirror ( .getClassLoader)'. Sau đó, bạn nhận được một biểu tượng phản chiếu Scala, có thể được kiểm tra bằng API phản chiếu Scala. –

+0

Tại sao bạn sử dụng 'universe.runtimeMirror (getClass.getClassLoader)' thay vì 'reflect.runtime.currentMirror' và' scala.reflect.classTag [C] .runtimeClass' thay vì 'classOf [C]'? Hóa ra là tôi đang làm việc tốt cho đến cuối cùng. Cảm ơn rất nhiều cho sự giúp đỡ, btw! –

Các vấn đề liên quan