2016-06-10 14 views
5

Scala'da yeni ve bir deyim varsa, bir deyim için işaretçiler arıyor.Çalışma zamanında bir Scala ifadesi nasıl derlenir/değerlendirilir?

I rasgele kullanıcı tarafından sağlanan Scala işlevleri istiyorum

(fonksiyonları referans bırakılır/benim kodunda tanımlanan olan sınıflar) bazı veriler uygulanır.

Örneğin: myprog.scala numaralı telefon numaramda tanımlanan foo(s: String): String ve bar(s: String): String işlevlerim var. Kullanıcı, bu gibi benim programı çalıştırır:

$ scala myprog data.txt --func='(s: Str) => foo(bar(s)).reverse' 

Bu veri dosyası aracılığıyla satır satır çalıştırmak ve bu çizgiye kullanıcı tarafından belirlenen işlevini uygulama sonucunu yayarlar olacaktır.

Ek noktalar için, kullanıcı tanımlı işlevde yan etki olmadığından emin olabilir miyim? Değilse, işlevi sadece sınırlı bir fonksiyon alt kümesi kullanmak için kısıtlayabilir miyim (güvende olmasını sağlayabilirim)?

+0

Freenode'daki lambdabot'un nasıl yazıldığına bakarsak, sorunlarınız benzer geliyor. – Reactormonk

cevap

2

@kenjiyoshida Scala kodunu eval gösterir güzel gist sahiptir. Eval bu kılavuzdan kullanıldığında, bir dönüş değeri belirtmediğinizde, Scala'nın varsayılan olarak Nothing sonucunu çıkarması durumunda çalışma zamanı hatasıyla sonuçlanacağını unutmayın.

scala> Eval("println(\"Hello\")") 
Hello 
java.lang.ClassCastException: scala.runtime.BoxedUnit cannot be cast to scala.runtime.Nothing$ 
    ... 42 elided 

scala> Eval[Unit]("println(\"Hello\")") 
Hello 

vs Güzel bir şekilde de kapsam ne varsa işler.

object Thing { 
    val thing: Int = 5 
} 

object Eval { 

    def apply[A](string: String): A = { 
    val toolbox = currentMirror.mkToolBox() 
    val tree = toolbox.parse(string) 
    toolbox.eval(tree).asInstanceOf[A] 
    } 

    def fromFile[A](file: File): A = 
    apply(scala.io.Source.fromFile(file).mkString("")) 

    def fromFileName[A](file: String): A = 
    fromFile(new File(file)) 

} 

object Thing2 { 
    val thing2 = Eval[Int]("Thing.thing") // 5 
} 

util-eval için kullanılan Twitter'ın util paketini, ama bu (derlenmiş zaman ve aynı zamanda bir derleyici hata tetikler) artık kullanımdan kaldırıldı gibi görünüyor.

Sorunuzun ikinci kısmına gelince, cevap hayır gibi görünmektedir. Varsayılan Predef'u devre dışı bırakıp kendiniz içe aktarsanız bile, bir kullanıcı tam işlevli paket adıyla bu işlevlere her zaman ulaşabilir. ya da çok az (Belki de eval geçmeden önce, öncelikle dize ayrıştırmak ve daha sonra bir beyaz listeye karşı karşılaştırmak için Scala'nın scala.tools.reflect.ToolBox kullanabilirsiniz, ancak el Scala AST sterilize kod yazılması olacağım beri o noktada işler çok kıllı alabilir en az tehlikeli girdiyi reddetmek). Kesinlikle "deyimsel bir çözüm" gibi görünmüyor.

0

Bu

import javax.script.*; 
ScriptEngine e = new ScriptEngineManager().getEngineByName("scala"); 
e.getContext().setAttribute("label", new Integer(4), ScriptContext.ENGINE_SCOPE); 
try { 
    engine.eval("println(2+label)"); 
} catch (ScriptException ex) { 
    ex.printStackTrace(); 
} 
(ayrıca scala.tools.nsc.Interpreter ama bu hala kullanılabilir emin değilim kullanarak bahseder) https://issues.scala-lang.org/browse/SI-874

bkz standart Java JSR 223 betik motoru kullanarak mümkün olmalıdır

İlgili konular