2009-08-19 9 views
4

Ich bewerte Sprachen für eine rechnerorientierte App, die eine easy eingebettete Skriptsprache für Endbenutzer benötigt. Ich habe darüber nachgedacht, Scala als Hauptsprache und Jython für die Skriptschnittstelle zu verwenden. Ein Anreiz von Scala ist, dass ich Methoden wie :* für die elementweise Multiplikation eines Matrixobjekts definieren und mit der Infix-Syntax a :* b verwenden kann. Aber: * ist kein gültiger Methodenname in Python. Wie geht Jython damit um?Infix-Operatoren in Scala und Jython

Ich würde Scala als Skriptsprache aufgrund seiner Flexibilität verwenden. Aber selbst mit typischem Schluss sind die val und var und die erforderlichen Typdefinitionen für Laien, die an dynamische Sprachen wie Matlab gewöhnt sind, zu viel. Im Vergleich dazu hat Boo die Option -ducky Option, die funktionieren könnte, aber ich möchte lieber auf der JVM als .NET bleiben. Ich nehme an, dass es für Scala keine -ducky gibt.

Generell sollten Sie Folgendes beachten DSL (von http://www.cs.utah.edu/~hal/HBC/) eine Latent Dirichlet Allocation zu modellieren:

model { 
     alpha  ~ Gam(0.1,1) 
     eta  ~ Gam(0.1,1) 
     beta_{k} ~ DirSym(eta, V)   , k \in [1,K] 
     theta_{d} ~ DirSym(alpha, K)   , d \in [1,D] 
     z_{d,n} ~ Mult(theta_{d})   , d \in [1,D] , n \in [1,N_{d}] 
     w_{d,n} ~ Mult(beta_{z_{d,n}})  , d \in [1,D] , n \in [1,N_{d}] 
} 

result = model.simulate(1000) 

Diese Syntax ist grandios (im Vergleich zu PyMCMC zum Beispiel) für Benutzer, die mit hierarchischer Bayes-Modellierung. Gibt es eine Sprache auf der JVM, die es leicht macht, eine solche Syntax zu definieren, sowie Zugang zu einer grundlegenden Skriptsprache wie Python?

Gedanken geschätzt.

+0

Nachdem ich die Diskussion hier gelesen habe, habe ich meine Antwort dahingehend überarbeitet, dass ich deine eigene maßgeschneiderte DSL benutze und sie parsiere ... Basierend auf deiner Problemdomäne denke ich, dass es der beste Weg ist. –

Antwort

0

EDIT:

Denn die Diskussion lesen, wahrscheinlich der beste Weg zu gehen, ist die Grammatik Ihres DSL zu definieren und es dann mit dem eingebauten Parsing-Dienstprogramme von scala zu analysieren.

Ich bin mir nicht sicher, was Sie versuchen zu erreichen. Ist Ihre Skriptsprache mehr ein "Was" oder eines "Wie" Typ? Das Beispiel, das Sie mir gegeben haben, ist ein "was" DSL -> Sie beschreiben, was Sie erreichen wollen, und kümmern sich nicht um die Implementierung. Dies sind die am besten verwendeten Sprachen, um ein Problem zu beschreiben, und nach der Domain, für die Sie die App erstellen, ist dies der beste Weg. Der Benutzer beschreibt das Problem nur in einer Syntax, die der Problemdomäne sehr vertraut ist. Die Anwendung analysiert diese Beschreibung und verwendet sie als Eingabe, um die Simulation auszuführen. Das Erstellen einer Grammatik und das Parsen mit den Scala-Parsing-Dienstprogrammen ist wahrscheinlich der beste Weg (Sie möchten nur eine kleine Teilmenge von Features für die Benutzer verfügbar machen).

Wenn Sie ein "wie" -Skript benötigen, dann ist die Verwendung einer bereits etablierten Skriptsprache der richtige Weg (es sei denn, Sie möchten Schleifen, grundlegende Datenstrukturen usw. selbst implementieren).

Bei der Entwicklung eines Systems müssen immer Abstriche gemacht werden. Hier ist es zwischen der Anzahl der Features, die Sie dem Benutzer zur Verfügung stellen möchten, und der Knappheit Ihres Skripts. Ich selbst werde so wenige Funktionen wie möglich aufführen, um die Aufgabe zu erledigen, und zwar auf eine "wie" - Weise - der Benutzer muss nicht wissen, wie er sein Problem simulieren wird, wenn die Simulation es gibt korrekte Ergebnisse und läuft in angemessener Zeit.

Wenn Sie dem Benutzer eine vollständige Skriptsprache zur Verfügung stellen, wird Ihr DSL nur eine kleine API in dieser Skriptsprache sein, und der Benutzer muss eine vollständige Sprache lernen, um seine volle Leistungsfähigkeit nutzen zu können. Und Sie möchten vielleicht nicht, dass ein Benutzer seine volle Leistung nutzt (er kann Ihre App zerstören!). Warum würden Sie beispielsweise die TCP-Socket-Unterstützung bereitstellen, wenn Ihre Anwendung keine Verbindung zum Internet herstellen muss? Das könnte ein mögliches Sicherheitsloch sein.

-- Der folgende Abschnitt beschreibt mögliche Skriptsprachen. Meine obige Antwort rät davon ab, sie zu verwenden, aber ich habe die Diskussion der Vollständigkeit überlassen.

Ich habe keine Erfahrung damit, aber schauen Sie sich Groovy. Es ist eine dynamisch typisierte Skriptsprache für die JVM (die JVM-Unterstützung wird wahrscheinlich in JDK 7 aufgrund von invokedynamic besser werden). Es hat auch gute Unterstützung für operator overloading und writing DSLs. Leider hat es keine Unterstützung für benutzerdefinierte Operatoren, zumindest nicht meines Wissens.

Ich würde immer noch mit Scala gehen (teilweise weil ich statische Typisierung mag und ich finde seine Art Schlussfolgerung gut :). Die Unterstützung für die Skripterstellung ist ziemlich gut und Sie können fast alles wie eine Unterstützung in der Muttersprache aussehen lassen (schauen Sie sich zum Beispiel die Actor-Bibliothek an!). Es hat auch eine sehr gute Unterstützung für funktionale Programmierung, die Skripte sehr kurz und prägnant machen kann. Und als Vorteil stehen Ihnen alle Möglichkeiten der Java-Bibliotheken zur Verfügung.

Um scala als Skriptsprache zu verwenden, setzen Sie Ihr Skript einfach in eine Datei mit der Endung .scala und führen Sie dann scala filename.scala aus. Eine Diskussion finden Sie unter Scala as a scripting Language, Vergleichen von Scala mit JRuby.

+0

Ich bin versucht, nur mit Hilfe von Scala, aber alle 'val' 'var '' new 'wird nicht an Benutzer ansprechen, die an Matlab gewöhnt sind. Es ist ein Schritt nach unten, kein Schritt nach oben. Gleichermaßen wollen Nicht-Programmierer-Benutzer nicht über Typen denken ("Int" vs. "Double"), wenn einfache Funktionen definiert werden. – Tristan

2

Persönlich denke ich, dass Sie den Overhead von Scala überbewerten. Zum Beispiel diese:

alpha  ~ Gam(10,10) 
mu_{k} ~ NorMV(vec(0.0,1,dim), 1, dim)  , k \in [1,K] 
si2  ~ IG(10,10) 
pi  ~ DirSym(alpha, K) 
z_{n}  ~ Mult(pi)       , n \in [1,N] 
x_{n}  ~ NorMV(mu_{z_{n}}, si2, dim)  , n \in [1,N] 

könnte als

def alpha =     Gam(10, 10) 
def mu = 1 to 'K map (k => NorMV(Vec(0.0, 1, dim), 1, dim) 
def si2 =     IG(10, 10) 
def pi =     DirSym(alpha, 'K) 
def z  = 1 to 'N map (n => Mult(pi)) 
def x  = 1 to 'N map (n => NormMV(mu(z(n)), si2, dim)) 

In diesem speziellen Fall geschrieben werden, wurde fast nichts getan, außer definieren Gam, Vec, NorMV, etc, und erstellen Sie eine implizite Definition von Symbol zu Int oder Double, Lesen von einer Tabelle, in der Sie solche Definitionen später speichern (wie mit einem loadM Äquivalent). Solche impliziten Definitionen wie diese gehen würde:

import scala.reflect.Manifest 
val unknowns = scala.collection.mutable.HashMap[Symbol,(Manifest[_], Any)]() 
implicit def getInt(s: Symbol)(implicit m: Manifest[Int]): Int = unknowns.get(s) match { 
    case Some((`m`, x)) => x.asInstanceOf[Int] 
    case _ => error("Undefined unknown "+s) 
} 
// similarly to getInt for any other desired type 

es als solches auch geschrieben werden könnte:

Model (
    'alpha -> Gam(10, 10), 
    'mu -> 'n -> NorMV(Vec(0.0, 1, dim), 1, dim)  With ('k in (1 to 'K)), 
    'si2  -> IG(10, 10), 
    'pi  -> DirSym('alpha, 'K), 
    'z -> 'n -> Mult('pi)       With ('n in (1 to 'N)), 
    'x -> 'n -> NorMV('mu of ('z of 'n), 'si2, dim)) With ('n in (1 to 'N)) 
) 

In diesem Fall Gam, Mult usw. benötigen würde ein bisschen anders, definiert werden zu handhaben die Symbole werden ihnen übergeben. Das Übermaß an '' 'ist jedoch definitiv nervig.

Es ist nicht wie HBC keine eigenen Idiosynkrasien es hat, wie die gelegentliche Notwendigkeit Typdeklarationen Unterstrichen, bevor Indizes, die gelegentliche Notwendigkeit „~“ mit „\in“, oder auch die umgekehrten Schrägstrich zu ersetzen, die vorausgehen muss der spätere. Solange es einen wirklichen Nutzen davon gibt, statt HBC, MathLab oder was auch immer die Person gewohnt ist, werden sie sich ein bisschen ärgern.

+0

Um. Der Autor der Frage _likes_ die Syntax, die er in Scala für diesen Fall bekommen kann (der, den Sie versuchen, durch etwas anderes zu ersetzen). Die Defs in Ihrem vorgeschlagenen Ersatz fallen in die gleiche Kategorie wie alle Val und Var, die er lieber vermeiden würde. –

+1

Sie haben ihn falsch verstanden. Die Syntax, die er zeigt, wenn Sie dem Link folgen, wird von etwas bereitgestellt, das HBC genannt wird. Das würde er gerne haben, wenn möglich. Nun, ich adressiere genau diesen Einwand von Ihnen, den Sie zitieren, und behaupte, dass es nicht so schlimm ist, wie er denkt. –

+0

Das stimmt, tut mir leid. Trotzdem ist eine Menge 'Def' wahrscheinlich nicht viel besser als' '' für ihn. –

0

Keiner der offensichtlichen Verdächtigen unter den JVM-Skriptsprachen - JavaScript Rhino, JRuby, Jython und Groovy - unterstützt benutzerdefinierte Operatoren (die Sie wahrscheinlich benötigen). Auch Fan nicht.

Sie könnten versuchen, JRuby mit superators gem.

+0

Wann wurde JavaScript zu einer JVM-Sprache? –

+4

Im Jahr 1997, als die Rhino-ECMAScript-Implementation entwickelt wurde. Seit Java 6 ist Rhino eigentlich ein Standard-Teil der JRE (oder zumindest des JDK). –

+0

JVM-Sprachen sind Sprachen, die nach JVM-Bytecode kompiliert werden. Rhino macht das nicht, oder? – skaffman