Ich frage mich, was die technischen Implementierungsunterschiede zwischen C # und Scala sind und wie sich beide Lösungen im Vergleich zu den Implementierungsideen und -bedenken verhalten, die in der E-Mail Peek Past Lambda von Brian Goetz an die Mailingliste von Project Lambda (JSR 335) geäußert wurden .
Aus der E-Mail:
Wir untersuchten den Weg von "Vielleicht sollten Lambdas nur Instanzen der inneren Klasse sein, die wirklich einfach wären", kamen aber schließlich zu der Position "Funktionen sind eine bessere Richtung für die Zukunft der Sprache".
und weiter:
Die Sicht der Lambda-Objekte auf die Welt steht im Konflikt mit dieser möglichen Zukunft. Die Sicht der Lambdas-Are-Functions auf die Welt tut dies nicht, und diese Flexibilität beizubehalten, ist einer der Punkte, die dafür sprechen, Lambdas nicht mit dem Aussehen von Objektivität zu belasten.
Fazit:
Lambdas-are-Funktionen öffnen Türen. Lambdas-are-Objekte schließen sie.
Wir ziehen es vor, die Türen offen zu sehen.
Und ein Kommentar von einer Person im Reddit-Thread lautet:
Ich habe Neal Gafter darüber eine E-Mail geschickt, und nach meinem begrenzten Verständnis seiner Erklärung sind C # und das aktuelle Java-Design insofern ziemlich ähnlich, als Delegates tatsächlich Objekte und keine Funktionstypen sind. Anscheinend glaubt er, dass Java aus den Nachteilen von C # -Lambdas lernen und diese vermeiden sollte (ähnlich wie C # aus den Nachteilen von Java gelernt und sie am Anfang vermieden hat).
Warum bietet der Ansatz "Lambdas-Are-Functions" in Zukunft mehr Möglichkeiten als "Lambdas-Are-Objects"? Kann jemand erklären, welche Unterschiede bestehen und wie sie sich darauf auswirken, wie Code geschrieben wird?
Angesichts der Tatsache, dass die Dinge in Scala "einfach funktionieren", denke ich immer wieder, dass mir etwas an den in C # / Java (8) gewählten / vorgeschlagenen Ansätzen fehlt.
Antworten:
Ich denke, die Diskussion zwischen Objekten und Funktionen ist ein roter Hering. Wenn die Frage lautet: "Ist ein Lambda eine Funktion oder ein Objekt?" Die Antwort sollte ja sein .
Darum geht es bei erstklassigen Funktionen: Sie werden nicht anders behandelt als jeder andere Typ. Java schafft es bereits, die Unterschiede zwischen Objekt- und primitiven Typen größtenteils zu ignorieren (und Scala noch besser). Ob also ein Lambda eine Unterklasse von Objekt oder ein neuer primitiver Typ ist oder etwas anderes, ist für die Sprache nicht wirklich wichtig. Wichtig ist, dass Sie Ihre Lambdas in Sammlungen ablegen, sie zum Aufrufen weitergeben, sie aufrufen und alles andere tun können, was Sie mit einem Objekt oder einer Methode tun möchten.
Scala erreicht dies durch die Verwendung eines Wrapper-Objekts mit einer aufgerufenen Methode,
apply
die mit just aufgerufen werden kann()
, sodass es wie ein Methodenaufruf aussieht. Das funktioniert prächtig; Die meiste Zeit brauchen Sie sich nicht einmal darum zu kümmern, ob Sie eine Methode haben oder die Apply-Funktion eines Funktionsobjekts aufrufen.quelle
Von dem, was ich verstehe, es ist mehr darüber , wie die Lambda - Ausdrücke sind als an dem primären Sprachniveau. Wie die E-Mail sagt,
Ich denke, das fasst deine Frage ganz gut zusammen. Wenn Sie erklären, dass "Lambdas Objekte sind", dann sind sie nur ein Objekt einer bestimmten Klasse und Sie stecken damit fest. Wenn Sie dagegen "Lambdas sind Funktionen" deklarieren, haben Sie semantisch ein viel besseres Spielfeld. Java 1.7 kompiliert sie möglicherweise zu Objekten, sodass sie zu diesem Zeitpunkt praktisch identisch sind.
Mit Java 1.8 oder 1.9 kann sich jedoch die Sprache ändern (z. B. umgestaltete Strukturtypen), sodass Funktionen wesentlich flexibler verwendet werden können. Wenn "Lambdas Objekte" wären, wären diese Änderungen nicht abwärtskompatibel, und Sie müssten ein neues Konzept einführen, um den vorhandenen Code der Leute nicht zu beschädigen. Aber wenn
javac
Lambdas nur leise in Objekte hinter den Kulissenjavac
konvertiert werden, kann das neue Lambdas in beliebige konvertieren, solange die Semantik noch gültig ist.quelle
foreach
,map
,filter
zu den Sammlungen.Meistens will er sich einfach nicht zu früh auf etwas festlegen. Ich sehe keinen Grund, der über die von ihm vorgelegte Löschung hinausgeht, aber das ist in der Tat ein sehr starker Grund.
Betrachten Sie diese Methoden in Scala
Regex
:Einfacher wäre es, wenn sie einfach so wären:
Dies ist leider nicht möglich, da diese beiden Funktionen beim Löschen identisch sind . Aber in Ordnung, diese Funktionen haben etwas anderes zu tun, so dass ein anderer Name durchaus gerechtfertigt ist.
Allerdings ist a
Match
etwas sehr Nützliches, aber die meiste Zeit möchten Sie entweder die passendeString
oder die Liste der Untergruppen. Wir möchten folgendes haben:Wegen Löschung nicht möglich. Ich habe mich für dieses Beispiel entschieden, weil ich direkt daran beteiligt war, aber ich habe mindestens ein halbes Dutzend Fragen zu Stack Overflow gesehen, in denen gefragt wurde, warum eine Überladung illegal ist, die durch genau dieses Problem verursacht wird.
Und dann bedenken Sie, dass Scalas Pattern Matching und Javas
instanceof
wegen Löschung praktisch unbrauchbar sind.Ich halte es für angemessen, Funktionstypen zu verzögern, bis dieses Problem behoben ist. Immerhin gibt es in der JVM viele Sprachen, und Java ist keine sich schnell entwickelnde Sprache.
quelle