Die Komplexität des aktuellen Lambda Vorschlag der Java 7? (August 2010)
-
25-09-2019 - |
Frage
Einige Leute sagen, dass jede Programmiersprache ihr „Komplexität Budget“ hat, die es seinen Zweck zu erreichen, nutzen kann. Aber wenn die Komplexität Budget erschöpft ist, wird jede noch so kleine Veränderung zunehmend kompliziert und schwer in einer rückwärtskompatibel Weise zu implementieren.
Nach dem Lesen der aktuellen vorläufigen Syntax für Lambda (≙ Lambda-Ausdrücke, Ausnahme Transparenz, Verteidiger Methoden und Verfahren Referenzen) ab August 2010 ich frage mich, wenn die Leute bei Oracle vollständig Java Komplexität Budget ignoriert, wenn solche Änderungen berücksichtigen.
Das sind die Fragen, die ich bin über - einige von ihnen mehr über die Sprache Design im Allgemeinen:
- Sind die vorgeschlagenen Ergänzungen vergleichbar Komplexität nähert sich anderen Sprachen gewählt haben?
- Ist es generell möglich, solche Zusätze zu einer Sprache hinzuzufügen und Schutz der Entwickler von der Komplexität der Implementierung?
- Ist diese Zusätze ein Zeichen Erreichen des Endes der Entwicklung von Java-as-a-Sprache oder dies zu erwarten, wenn eine Sprache mit einer großen Geschichte zu ändern?
- Haben Sie andere Sprachen einen völlig anderen Ansatz an dieser Stelle der Sprachevolution genommen?
Danke!
Lösung
Ich habe folgte nicht den Prozess und die Entwicklung des Lambda-Java 7 Vorschlag, ich bin nicht einmal sicher, was die neueste Vorschlag Formulierung ist. Betrachten Sie dies als eine Tirade / Meinung eher als Aussagen der Wahrheit. Ebenfalls, Ich habe nicht Java seit Jahren verwendet, so dass die Syntax möglicherweise rostig und falsch an Orten.
Erstens, was ist Lambda-Ausdrücke auf die Java-Sprache? Syntethischer Zucker. Während im allgemeinen lambda ermöglicht Code kleine Funktionsobjekte zu schaffen, in Ort wurde diese Unterstützung bereits --to einige extent-- in der Java voreingestellt Sprache durch die Verwendung von inneren Klassen.
Wie viel besser ist die Syntax von lambdas? Wo es gerade outperform vorherige Sprachkonstrukte? Wo könnte es besser sein?
Für den Anfang, mag ich die Tatsache, dass es zwei verfügbare Syntax
für Lambda-Funktionen (aber das geht in der Linie von C #, so dass ich mein erraten
Meinung ist nicht weit verbreitet. Ich denke, wenn wir zu Zucker Mantel wollen, dann
#(int x)(x*x)
ist süßer als #(int x){ return x*x; }
selbst wenn die
Doppel Syntax fügt nichts anderes. Ich hätte es vorgezogen die
zweite Syntax, allgemeinere auf die zusätzlichen Kosten von Schriftfelter return
und
;
in den kurzen Versionen.
Um wirklich nützlich, lambda Variablen aus dem Anwendungsbereich nimmt in
wo sie definiert und von einer Schließung . Konsequent mit
Innere Klassen, Lambda-Ausdrücke sind auf beschränkt Capturing ‚effektiv
final‘Variablen. Übereinstimmung mit den bisherigen Funktionen der
Sprache ist ein nettes Feature, aber für die Süße, wäre es schön, zu sein
können Variablen erfassen, die neu zugeordnet werden können. Zu diesem Zweck,
sie erwägen, dass Variablen im Kontext präsentieren und
kommentierte mit @Shared
werden gefangen durch Verweis , so dass
Zuordnungen. Mir scheint dies seltsam, wie wie eine Lambda eine Variable verwenden können
wird am Ort der Deklaration der Variablen eher bestimmt als
wobei das Lambda ist definiert. Eine einzelne Variable könnte in mehr verwendet werden
als eine Lambda und diese Kräfte das gleiche Verhalten in allen von ihnen.
Lambdas versuchen tatsächliche Funktionsobjekte zu simulieren, aber der Vorschlag tut
nicht vollständig dort: die Parser einfach zu halten, jetzt, da bis zu
Bezeichnet eine Kennung entweder einen Gegenstand oder ein Verfahren, das gehalten wurde,
konsistent und ein Lambda-Aufruf erfordert eine !
nach dem Lambda mit
Name: #(int x)(x*x)!(5)
25
zurück. Dies bringt eine neue Syntax
für Lambdas zu verwenden, die von dem Rest der Sprache unterscheiden, wobei
!
steht irgendwie als synonim für .execute
auf einem virtuellen generic
Schnittstelle Lambda<Result,Args...>
aber, warum nicht machen es vollständig?
Eine neue generische (virtuelle) Schnittstelle Lambda
erstellt werden kann. Es würde
müssen virtuell sein als die Schnittstelle nicht eine reale Schnittstelle, sondern ein
Familie solcher: Lambda<Return>
, Lambda<Return,Arg1>
,
Lambda<Return,Arg1,Arg2>
... Sie könnten eine einzige Ausführung definieren
Verfahren, das Ich mag würde wie C ++ operator()
sein, aber wenn es das ist
eine Belastung dann wäre ein anderer Name in Ordnung sein, die !
als umarmend
Abkürzung für die Ausführung der Methode:
interface Lambda<R> {
R exec();
}
interface Lambda<R,A> {
R exec( A a );
}
Dann muss der Compiler übersetzt nur identifier!(args)
zu
identifier.exec( args )
, die einfach ist. Die Übersetzung der
Lambda-Syntax erfordern würde die Compiler die richtigen zu identifizieren
Schnittstelle implementiert werden und könnte als abgestimmt werden:
#( int x )(x *x)
// translated to
new Lambda<int,int>{ int exec( int x ) { return x*x; } }
Dies würde auch Benutzer erlauben, Innere Klassen zu definieren, die verwendet werden können,
wie Lambda-Ausdrücke, in komplexeren Situationen. Zum Beispiel, wenn Lambda
Funktion benötigt eine Variable als @Shared
in einer kommentierten einzufangen
Nur-Lese-Weise oder aufrechtzuerhalten, die den Zustand des erfassten Objekts an der
Ort der Erfassung, würde manuelle Umsetzung des Lambdas sein
zur Verfügung:
new Lambda<int,int>{ int value = context_value;
int exec( int x ) { return x * context_value; }
};
In einer Weise, ähnlich dem, was die aktuelle Innere Klassen-Definition ist, und damit natürlich sein, um aktuelle Java-Nutzer. Dies könnte be verwendet, beispielsweise in einer Schleife Multiplizierer Lambdas zu erzeugen:
Lambda<int,int> array[10] = new Lambda<int,int>[10]();
for (int i = 0; i < 10; ++i ) {
array[i] = new Lambda<int,int>{ final int multiplier = i;
int exec( int x ) { return x * multiplier; }
};
}
// note this is disallowed in the current proposal, as `i` is
// not effectively final and as such cannot be 'captured'. Also
// if `i` was marked @Shared, then all the lambdas would share
// the same `i` as the loop and thus would produce the same
// result: multiply by 10 --probably quite unexpectedly.
//
// I am aware that this can be rewritten as:
// for (int ii = 0; ii < 10; ++ii ) { final int i = ii; ...
//
// but that is not simplifying the system, just pushing the
// complexity outside of the lambda.
Dies würde Verwendung von Lambda-Ausdrücke und Methoden ermöglichen, die Lambda-Ausdrücke akzeptieren beide
mit der neuen einfachen Syntax: #(int x){ return x*x; }
oder mit dem mehr
komplexer manueller Ansatz für bestimmte Fälle, in denen die Zuckerschicht
interferiert mit der beabsichtigten Semantik.
Insgesamt glaube ich, dass der Lambda-Vorschlag verbessert werden kann verschiedene Richtungen, dass die Art und Weise fügt sie syntaktischer Zucker a Abstraktion undicht (Sie müssen extern mit Fragen befassen, die insbesondere das Lambda), und dass durch kein niedrigeres Niveau bereitstellt Schnittstelle macht es Benutzercode weniger lesbar in Anwendungsfällen, die nicht tun perfekt mit dem einfachen Anwendungsfall. :
Andere Tipps
Modulo einige Rahmen-Begriffsklärung Konstrukte, die fast alle dieser Methoden ergeben sich aus der tatsächlichen Definition einer Lambda-Abstraktion:
λx.E
Um Ihre Fragen zu beantworten, um:
Ich glaube nicht, gibt es keine besonderen Dinge, die die Vorschläge der Java-Community besser oder schlechter als irgendetwas anderes zu machen. Wie gesagt, es aus der mathematischen Definition folgt, und damit alle Gläubigen Implementierungen gehen fast genau die gleiche Form haben.
Anonymous erstklassige Funktionen auf imperativen Sprachen verschraubt sind in der Regel als ein Merkmal, um am Ende, dass einige Programmierer lieben und häufig verwenden, und dass andere ignorieren vollständig - deshalb ist es wahrscheinlich eine vernünftige Wahl ihm einig Syntax zu geben, die nicht verwirren Arten von Menschen, die das Vorhandensein dieser besonderen Sprache-Funktion zu ignorieren wählen. Ich denke, die Komplexität und die Einzelheiten der Umsetzung versteckt ist, was sie unter Verwendung von Syntax, dass Mischungen gut mit Java zu tun versucht haben, aber das hat keine wirkliche Konnotation für Java-Programmierer.
Es ist wahrscheinlich wünschenswert, dass sie einige Bits der Syntax zu verwenden, die bestehenden Definitionen nicht erschweren werden, und so dass sie leicht in den Symbolen eingeschränkt sind, können sie wählen, als Betreiber und solche verwenden. Sicherlich Java Beharren auf verbleibenden rückwärtskompatibel Grenzen die Sprachentwicklung leicht, aber ich glaube nicht, das ist unbedingt eine schlechte Sache. Der PHP-Ansatz ist am anderen Ende des Spektrums (das heißt: „Hey Jungs, mal Pause alles jedes Mal gibt es eine neue Point-Release!“). Ich glaube nicht, dass Java die Entwicklung von Natur aus mit Ausnahme von einigen der grundlegenden Lehren des Designs beschränkt ist - z.B. Einhaltung der OOP-Prinzipien, VM-basiert.
Ich denke, dass es sehr schwierig ist, starke Aussagen über die Sprache Entwicklung von Java-Perspektive zu machen. Es ist in einer ziemlich einzigartigen Position. Zum einen ist es sehr, sehr beliebt, aber es ist relativ alt. Microsoft hatte den Vorteil von mindestens 10 Jahren im Wert von Java Vermächtnis, bevor sie beschlossen, selbst zu starten, eine Sprache „C #“ genannt zu entwerfen. Die Programmiersprache C gestoppt grundsätzlich überhaupt entwickelt. C ++ hat einige bedeutende Änderungen hatte, die jede allgemeine Akzeptanz gefunden. Java hat sich weiter durch eine langsame, aber konsistenten Prozess entwickeln -. Wenn alles, was ich denke, es ist besser, ausgestattet mit ähnlich großen installierten Code-Basen auf sich entwickelnden als alle anderen Sprachen zu halten
Es ist nicht viel komplizierter als Lambda-Ausdrücke in anderen Sprachen.
Consider ...
int square(x) {
return x*x;
}
Java:
#(x){x*x}
Python:
lambda x:x*x
C #:
x => x*x
ich glaube, der C # Ansatz etwas intuitiver ist. Persönlich würde ich lieber ...
x#x*x
Vielleicht ist das nicht wirklich eine Antwort auf Ihre Frage, aber das kann auf die Art und Weise Objective-c vergleichbar sein (was natürlich eine sehr enge Benutzerbasis im Gegensatz zu Java hat) wurde durch Blöcke erweitert (examples ). Während die Syntax nicht den Rest der Sprache (IMHO) passen, ist es eine sinnvolle Ergänzung und und die zusätzliche Komplexität in Bezug auf die Sprachfunktionen zum Beispiel mit einer geringeren Komplexität der gleichzeitigen Programmierung (einfache Dinge wie die gleichzeitige Iteration über ein Array wird belohnt oder komplizierte Techniken wie Grand Central Dispatch ).
Darüber hinaus sind viele gemeinsame Aufgaben einfacher, wenn Blöcke mit, zb ein Objekt ein Delegierter (oder - in Java-Jargon - „Listener“) für mehrere Instanzen der gleichen Klasse. In Java können bereits anonyme Klassen für diese Ursache verwendet werden, so dass Programmierer das Konzept kennen und kann sich nur ein paar Zeilen Quellcode verschonen Lambda-Ausdrücke verwenden.
In Objective-C (oder die Cocoa / Cocoa Touch-Frameworks), sind neue Funktionen jetzt oft nur zugänglich Blöcke verwenden, und es scheint, wie Programmierer sind sie schnell zur Annahme (vorausgesetzt, dass sie die Abwärtskompatibilität mit alten OS-Versionen aufgeben ).
Das ist wirklich ganz in der Nähe Lambda-Funktionen in der neuen Generation der C vorgeschlagen ++ (C ++ 0x) so glaube ich, haben Oracle Jungs bei den anderen Implementierungen sieht vor ihre eigenen kochen.
http://en.wikipedia.org/wiki/C%2B%2B0x
[](int x, int y) { return x + y; }