Ich habe mir gestern das
2008 Lang.NET Video angeschaut und kurz die Doku überflogen. Ich finde zwar die Tatsache beeindruckend, dass jemand ein Jahr an seiner eigenen Sprache arbeitet, aber das Ergebnis ist dann doch nur ein C# mit anderer Syntax.
Wohl in der Versuch, alles statisch zu typisieren führt, zeigt z.B.
Scala. Prinzipiell klingt das Versprechen, Typfehler zur Übersetzungszeit zu finden gut, der Preis ist aber IMHO zu hoch und außerdem - wieso Übersetzungszeit? Programmiersprachen, die einen Edit-Compile-Test-Ritus benötigen sind so "letztes Jahrtausend", dass mir der Ansatz von Cobra, eine reine Compilersprache zu sein, missfällt.
In die Sprache eingebaute Unittests (statt diese im Kommentarstring zu verstecken) finde ich gut. Vor- und Nachbedingungen haben mich selten überzeugt, diese empfinde ich als entbehrlich. Dennoch: statische Typen sind natürlich nur ein Speziallfall von contracts und diese Erkenntnis vermisse ich ein bisschen in der Sprache.
Das floats nicht der Default für Arithmetik sind, ist eine gute Entscheidung.
Die Syntax finde ich zu einfach. Was ich damit meine, ich finde kaum Konstrukte, die helfen zu abstrahieren. Der nutzen des "?"-Operator ist IMHO eher fragwürdig, List Comprehensions sehen primitiver aus als das Python-Gegenstück, top-level-Funktionen gibt es gnauso wenig wie verschachtelte Klassen oder Funktionen wie es scheint. Und etwas wie "post while" ist eher irritierend. Mich persönlich stören auch noch die fehlenden ":" im Vergleich zu Python und die regel, dass man das "this" weglassen kann und dann einfach ".foo" schreibt statt den Empfänger immer explizit zu schreiben.
Ich hatte mir den Forth-Interpreter als Beispiel angeschaut. Daraus schließe ich, dass Pythons Mehrfachzuweisungen ebenfalls nicht gehen. Dafür darf man offenbar () bei Definitionen von Methoden ohne Parameter weglassen.
Wie Leonidas aus "self-hosted" einen Nachteil kreiert, finde ich interessant, ich kann aber diese Einschätzung nicht teilen. Ich halte es für einen großen Vorteil, hat man doch wenigstens den Beweis, dass die Sprache zur Entwicklung von Sprachen taugt. Ich sehe das eher als Praxistest und Gelegenheit, die passenden Werkzeuge zu entwickeln. Da Cobra ja C# erzeugt, sollte es dem Erfinder daher doch möglich sein, ein VisualStudio-Plugin (ich vermute mal, dass man diese in C# bauen kann) in Cobra zu bauen. Es wäre jedenfalls IMHO viel einfacher, ein in Python geschriebenes Python zu erweitern als eines, das in C entwickelt ist - schon der Buildprocess ist dort nicht ohne.
Das etwa Squeak-Smalltalk in (einem Subset von) Squeak geschrieben wurde, war IMHO immer ein großer Vorteil. Die VM wird da über den Umweg GCC erstellt.
Ich finde BlackJacks Argument "das war schon immer" bgzl. floats wenig überzeugend. Scheme etwa unterscheidet seit je her bei numerischen Typen "exact" und "inexact" und man warnt vor zweiterem. Bei fast allen Smalltalk-Systemen die ich kenne, wird standardmäßig mit Brüchen gearbeitet, wenn Ganzzahlen nicht reichen und "floats" muss man wieder explizt konvertieren. Sehr praktisch, wenn "1 / 3 * 3" auch wirklich wieder "1" ist - und zwar, weil das System Bruchrechnung beherrscht und kürzen kann.
Das Cobra schneller als Python ist, glaube ich im Gegensatz zu BlackJack durchaus, denn wir sehen da ja "nur" ein C# oder VB mit anderer Syntax. Dynamische Aspekte von Python, wie z.B. das __dict__ einer Klasse zur Laufzeit ändern zu können, sind soweit ich es sehe, in Cobra überhaupt nicht möglich. Etwas wie
Code: Alles auswählen
class ForthMachine
var _stack as Stack<of Word>
var _definitions as Dictionary<of Word, Definition>
def init
_stack = Stack<of Word>()
_definitions = Dictionary<of Word, Definition>()
.define('quit', 'built-in:quit')
class Word
implements IComparable<of Word>
def compareTo(other as Word) as int
if .isInt
if other.isInt
return .int.compareTo(other.int)
else
return -1
# usw..
kann man 1:1 in C# und damit dann auch in IL kompilieren. Das ist dann natürlich genauso schnell und deutlich schneller als (C|Iron)Python, welches für jede Methode in einem Dictionary suchen muss.
Leonidas fragte noch, wie die DLR funktioniert. Meines Wissens stellt die DLR einen abstrakten AST als Rahmenwerk zur Verfügung, der für jede Sprache konkretisiert werden muss, gemeinsame Sprachfeatures wie if-Bedingungen oder while-Schleifen aber schon mal abbildet. Die DLR macht es daneben einfach, aus dem AST IL-Bytecode zu generieren, wieder zu laden und dann von der .NET-VM ausführen zu lassen. Methodensuche, Methodenaufruf, usw. sind Sprachspezifisch und müssen jeweils implementiert werden. DLR legt hier den Einsatz von CallSite-Objekten (das sind AFAIK Polymorphic Inline Caches, PICs, ein typischer Weg, dynamische Sprachen schneller zu machen) nahe, die Ergebnisse vorheriger Suchen aufbewahren. Deren Verwaltung ist jedoch nicht trivial und diese machen es dann auch schwierig, Sprachen per DLR auf .NET zu ziehen. Dennoch ist es einfacher als bei Java, wo man sie eine entsprechende Infrastruktur selber bauen müsste - wie es z.B. JRuby oder Groovy machen. Allerdings ist die Java-VM deutlich besser, was Optimierungen angeht und man muss hier nicht so viel Aufwand treiben, sagt Sun. Dafür kann der Bytecode nicht so viel und man muss etwa für jede Python-Funktion oder Ruby-Methode eine Java-Klasse mit eigenem ClassLoader erzeugen, während .NET hier nur Delegates für mehrere Methoden einer Klassen braucht. Aber auch hier gibt es Probleme, wenn man Methoden zur Laufzeit ändern will, irgendwie muss man mit AppDomains was machen, was letztlich noch aufwendiger ist als die ClassLoader von Java.
Prinzipiell funktioniert JRuby oder Jython wohl so:
Code: Alles auswählen
public abstract class PyFunction extends PyObject {
public abstract PyObject call(PyFrame f, PyTuple args, PyDict kw);
...
}
public class PyBuiltinFunctionAbs extends PyFunction {
public PyObject call(PyFrame f, PyTuple args, PyDict kw) {
if (args.len() != 1) return raise(TypeError, "abs() takes ...");
PyObject o = args.getitem(f, 0);
if (o isinstanceof PyInt) {
PyInt i = (PyInt) o;
if (i.value < 0) return PyInt.make(-i.value);
return i;
}
if (o isinstanceof PyInstance) {
o = o.getattr(f, "__abs__");
if (o != null) return o.call(f, args, kw);
return raise(AttributeError, "...");
}
return raise(TypeError, "bad operand type for abs()...")
}
}
static {
builtins = new PyModule();
builtins.def("abs", new PyBuiltinFunctionAbs());
}
Für jeden noch so kleinen Funktionsaufruf muss bei Python gewaltig viel Code durchlaufen werden.
Was ich mir bei einer neuen Sprache wie Cobra wünschen würde, wären z.B. sealed classes ähnlich wie sie Dylan kennt. Damit könnte man dem System sagen, es kann gefahrlos die __dict__ wegoptimieren, man wird sie nie verändern. Andererseits, offene Klassen sind so verdammt praktisch.
Fazit: Müsste ich VB oder C# mit Super-IDE-Support aber nicht so doller Syntax gegen Cobra mit vielleicht netterer Syntax aber zur Zeit ohne IDE Support abwägen, würde wohl C# gewinnen. Wenn schon neue Sprache, dann auch bitte neue Konzepte und nicht einfach nur eine andere Syntax.
Stefan