Erstklassige Funktionen

11

Ich habe dieses Wochenende angefangen, mich ernsthaft mit Lisp zu beschäftigen (womit ich meine, dass ich nur Lisp gelernt habe und nicht zu Projekten in C # zurückgekehrt bin) und muss sagen, dass ich es liebe. Ich habe mich mit anderen funktionalen Sprachen (F #, Haskell, Erlang) beschäftigt, aber die Auslosung, die Lisp mir gegeben hat, nicht gespürt.

Jetzt, da ich weiterhin Lisp lerne, frage ich mich, warum nicht funktionierende Sprachen keine erstklassigen Funktionen unterstützen. Ich weiß, dass Sprachen wie C # ähnliche Aufgaben mit Delegaten ausführen können und dass Sie in gewissem Umfang Zeiger auf Funktionen in C / C ++ verwenden können. Gibt es jedoch einen Grund, warum dies in diesen Sprachen niemals zu einer Funktion werden würde? Gibt es einen Nachteil, wenn man Funktionen erstklassig macht? Für mich ist es äußerst nützlich, daher weiß ich nicht, warum mehr Sprachen (außerhalb des Funktionsparadigmas) es nicht implementieren.

[Bearbeiten] Ich schätze die bisherigen Antworten. Da mir gezeigt wurde, dass viele Sprachen jetzt erstklassige Funktionen unterstützen, werde ich die Frage neu formulieren: Warum würde es so lange dauern, bis Sprachen sie implementieren? [/Bearbeiten]

Jetti
quelle
3
Ich bin nicht der Meinung, dass C # "ähnliche Dinge" tun kann. Ich würde sagen, es hat erstklassige Funktionen in jeder Hinsicht (was Ihre Prämisse ruiniert). Es hat eine Syntax für Funktionsliterale, Sie können Funktionen in Variablen usw.
einfügen
@Logan - Ich habe darüber diskutiert, ob C # -Beispiele enthalten sind, habe mich aber entschieden, auf diesem Wikipedia-Eintrag zu basieren . Dem Eintrag zufolge gibt es keine echten erstklassigen Funktionen, da "die Objekte, die den dynamischen Status der Funktion enthalten, manuell erstellt werden müssen". Wenn dies jedoch eine falsche Aussage ist, würde ich gerne wissen warum! (Immerhin bin ich hier, um zu lernen und nicht in meinen Wegen stecken zu bleiben!)
Jetti
2
Dieser Wikipedia-Eintrag ist veraltet. Ein modernes C # liefert ein richtiges Lambda.
SK-Logik
Ich denke, dieser Absatz ist schlecht geschrieben. Es scheint zu sagen, dass C ++ - Funktoren nicht erstklassig sind und C # -Delegierte auch nicht? Obwohl ich dem Argument für Funktoren zustimmen könnte, bin ich mir nicht sicher, ob ich es für C # -Delegierte tun würde. Es heißt auch "(siehe Lambda-Lifting)", was eine Aussage über diese Sprachen ist, die lexikalische Abschlüsse unterstützen und nicht "als Werte fungieren". Sie können eins ohne das andere haben. Selbst wenn dies der Fall ist, gilt dies nicht für C #, sondern für lexikalische Verschlüsse. Ein Teil des Problems ist, dass "erstklassige Funktion" ein vager Begriff sein kann.
Logan Capaldo
1
@Logan & SK-Logic - Ich freue mich über Ihr Feedback und Ihre konstruktive Haltung. Ich lerne noch und es ist sehr schön, nicht geflammt zu werden, deshalb weiß ich das zu schätzen. Vielen Dank für die Kommentare und Antworten!
Jetti

Antworten:

5

C #, VB.NET, Python, JavaScript, jetzt bietet sogar C ++ 0x erstklassige Funktionen.

Aktualisieren:

Eine Implementierung von Verschlüssen erfordert Lambda-Lifting - eine Technik, die den imperativen Programmierern ursprünglich recht fremd war. Für ordnungsgemäße erstklassige Funktionen (einschließlich Schließungen) ist zumindest eine gewisse Unterstützung durch die Laufzeit und die VM erforderlich. Es dauerte auch einige Zeit, um die alten Funktionstechniken in die imperative Welt zu übernehmen.

Und das Wichtigste: Erstklassige Funktionen können kaum verwendet werden, wenn keine Speicherbereinigung vorhanden ist. Es wurde erst kürzlich mit Java und folglich mit .NET in eine Massenprogrammierung eingeführt. Und der ursprüngliche Java-Ansatz bestand darin, die Sprache zu stark zu vereinfachen, um sie für die durchschnittlichen Programmierer verständlich zu halten. .NET folgte zuerst und trennte sich erst kürzlich von dieser (meiner Meinung nach rechtfertigten und angemessenen) Richtung.

All diese Konzepte brauchen Zeit, um von der Industrie verarbeitet zu werden.

SK-Logik
quelle
Ich habe die ursprüngliche Frage basierend auf den Antworten bearbeitet.
Jetti
Erstklassige Funktionen! = Verschlüsse (und GC ist für letztere wesentlich notwendiger). Obwohl, ja, sie sind eng miteinander verwandt und Sie sehen sie selten, wenn überhaupt, getrennt.
@delnan, ohne zumindest irgendeine Form von lexikalischen Schließfunktionen sind Funktionen nicht zusammensetzbar und zur Laufzeit nicht konstruierbar, was für eine erstklassige Funktionsdefinition obligatorisch ist.
SK-Logik
Nein. Sie können das Verweisen auf Variablen einschließender Bereiche nicht zulassen (oder die Werte der referenzierten Variablen zum Zeitpunkt der Funktionserstellung kopieren - keine Ahnung, ob dies als Abschluss gilt). Das Ergebnis ist nicht besonders nützlich, aber Funktionen können zur Laufzeit ohne Abschluss erstellt werden, sodass Sie (seltsame) erstklassige Funktionen haben.
1
@ SK-Logik: C ++ 0x bietet Schließungen ohne Speicherbereinigung mit dem üblichen Trick -> Wenn die Variable den Gültigkeitsbereich verlässt und Sie immer noch an einer Referenz festhalten, ist die Verwendung der Referenz ein undefiniertes Verhalten. Es ist also möglich ... es bringt nur den Honus auf den Entwickler.
Matthieu M.
5

Erstklassige Funktionen sind ohne Verschlüsse viel weniger interessant.

Schließungen sind ohne eine dynamische Verwaltung des Gültigkeitsbereichs (Garbage Collection) nicht wirklich möglich. Eines der Dinge, die C / C ++ so leistungsfähig machen, ist die Tatsache, dass es viel einfacher ist, eine Sprache zu kompilieren, in der Sie den Speicher manuell verwalten, sodass C / C ++ irgendwie aus der Gleichung herausgenommen wird.

Und dann ja, da ist die Frage der OOP-Auswirkungen. Sie haben keine Trennung mehr von Methoden und Eigenschaften. Methoden sind selbst Eigenschaften, die Funktionen als Werte akzeptieren. Was bedeutet es in diesem Zusammenhang wirklich, Methoden zu überladen, da Sie die dummen Dinge jederzeit einfach austauschen können? Können Sie das zum Beispiel wirklich zu Java hinzufügen, ohne einen großen Paradigmenwechsel in der gesamten Sprache einzuführen? Woher kommt der Vertrag oder das Gefühl der (IMO-falschen) Sicherheit, wenn Menschen wissen, dass das Konstrukt garantiert, dass es jedes Mal auf die gleiche Weise funktioniert? Es mag sinnvoll sein, an Objekte gebundene Funktionen als Methoden als einen anderen Organismus in Sprachen zu behandeln, die es Funktionen ermöglichten, unabhängig voneinander zu existieren, aber in Java ist dies eigentlich keine Option.

In JavaScript sind OOP und Funktionalität sehr eng miteinander verbunden, und ich persönlich würde es schwierig finden, erstklassige Funktionen in Sprachen, in denen sie nicht vorhanden waren, als alles andere als angeschraubt zu sehen. Dies erfordert jedoch eine Reihe anderer Paradigmenwechsel, einschließlich eines hohen Maßes an Veränderlichkeit in Objekten und ihren Methoden selbst sowie die Fähigkeit, Funktionen aufzurufen, als wären sie Mitglieder eines Objekts im laufenden Betrieb.

Sprachen sind nicht nur Tool-Sets voller Do-Hickeys, um die Dinge größtenteils zu erledigen. Das sind Paradigmen. Bündel von Ideen, Strategien und Meinungen, die alle auf eine Weise zusammenpassen, die miteinander verbunden ist (oder verbunden zu sein scheint). In vielen Fällen passen Funktionen wie Substantiv und Verb wirklich überhaupt nicht zum Paradigma oder sind bestenfalls unvollständig.

Trotzdem habe ich das Gefühl, dass mir ein Arm fehlt, wenn ich gezwungen bin, ohne sie zu codieren.

Erik Reppen
quelle
Sie können entweder alle Methoden als versiegelt behandeln oder nur die versiegeln, die Ihnen am wichtigsten sind, und es wird Ihnen gut gehen.
Alexei Averchenko
@AlexeiAverchenko Ich freue mich sagen zu können, dass ich nicht 100% sicher bin, was du damit meinst. Entschuldigung, ich habe deinen Kommentar bis jetzt verpasst. Googeln "versiegelte Methoden".
Erik Reppen
4

Das ist nicht wirklich unmöglich. Aber es ist noch eine weitere Funktion, und das Komplexitätsbudget ist begrenzt. Es kann vom Sprachdesigner als unnötig angesehen werden (oder auch nicht in den Sinn kommen) - "Warum zum Teufel müssten wir Funktionen weitergeben? Diese Sprache dient zum Programmieren eines Betriebssystems!". Es kann auch erhebliche Anstrengungen erfordern, um mit dem Rest der Sprache zu verschmelzen. Zum Beispiel kann ein Funktionstyp ernsthafte Ergänzungen des Typsystems erfordern (z. B. in Java), noch mehr, wenn Sie überladen sind (danke @Renesis für den Hinweis). Sie müssen auch einen Bibliothekscode bereitstellen, um das Lebensfähige nutzen zu können - niemand möchte sich mapselbst definieren .

Es könnte auch schwieriger werden, andere Ziele der Sprache zu erreichen:

  • Die Optimierung wird "schwieriger" (in vielen Fällen nicht wirklich schwieriger, erfordert jedoch andere Ansätze als Sie es gewohnt sind). Wenn beispielsweise globale Funktionen neu zugewiesen werden können, müssen Sie nachweisen, dass sie fniemals neu zugewiesen werden, bevor Sie sie inline setzen.
  • In ähnlicher Weise benötigen Sie einen intelligenten Compiler und JIT, um den damit verbundenen Overhead zu beseitigen und das Aufrufen so effizient (geschwindigkeits- und raummäßig ) zu gestalten, wie das Drücken von Argumenten und das Zurücksenden von Adressen und das Springen zu eine Adresse.
  • Wie bereits erwähnt, ist dies eine weitere vollständige Funktion und die ersten Schritte zur Unterstützung eines weiteren Paradigmas. Wenn Sie eine einfache Sprache wünschen, können Sie es sich möglicherweise nicht leisten , erstklassige Funktionen hinzuzufügen, ohne andere Dinge zu werfen (die Sie möglicherweise für viel wichtiger halten). aus.
  • Vielleicht passt es einfach nicht gut zum Rest der Sprache. Wenn Sie die Sprache so gestalten, dass sie z. B. die beste Inkarnation von OOP seit Smalltalk ist, möchten Sie sich vielleicht darauf konzentrieren, anstatt ein anderes, ganz anderes Paradigma anzubieten. Besonders wenn es schwierig ist, die beiden zu integrieren (siehe oben). N gut gemachte Paradigmen sind angenehmer zu programmieren als schlecht gemachte N + 1-Paradigmen.

Ebenso kann man sich fragen, warum eine Programmiersprache L1 kein Merkmal F der sehr unterschiedlichen Sprache L2 hat.


quelle
1

Ich denke, das erste Problem ist ein Missverständnis, dass objektorientiert und funktional nicht gemischt werden können. Eine kurze Liste der Sprachen, die zumindest von Wikipedia als beides beschrieben werden: JavaScript , ActionScript , Python , C # , F # .

Das zweite Problem scheint eine Definition erstklassiger Funktionen zu sein - warum betrachten Sie C # beispielsweise nicht als solche?

Ich bin kein Experte für funktionale Sprachen. Bitte korrigieren Sie mich in den Kommentaren, wenn ich falsch liege. Mein Verständnis ist jedoch, dass die Einbeziehung erstklassiger Funktionen selbst mehr oder weniger definiert, ob eine Sprache ein funktionales Paradigma unterstützt .

Was ist die eigentliche Frage?

So, die objektorientierte Verständnis Sprachen kann auch funktional sein, und diese Sprachen enthalten erstklassige Funktionen, es klingt wie die Frage nach dem Sie suchen sind warum einige objektorientierten Sprachen nicht First-Class - Funktionen enthalten?

Funktionsüberladung

Einer der Hauptgründe dafür ist die Schwierigkeit, erstklassige Funktionen zu definieren, wenn die Sprache auch die Funktionsüberladung unterstützt (Beispiel in Java):

public int dispatchEvent(Event event);
public int dispatchEvent(String event, Object data);

Auf welche dispatchEventFunktion würde sich eine Variable beziehen?

Klassenbasierte Programmierung

Klassenbasierte Programmierung hindert eine Sprache nicht daran, erstklassige Objekte zu unterstützen, kann sie jedoch verwirrender machen oder zu beantwortende Fragen hinzufügen.

ActionScript zum Beispiel als ECMAScript-Sprache begann in einem viel funktionaleren Paradigma wie JavaScript. Funktionen waren nicht von Natur aus an Objekte gebunden, sondern konnten im Wesentlichen mit jedem Objekt aufgerufen werden, da es zum Zeitpunkt der Ausführung den Gültigkeitsbereich hatte.

Wenn Sie (nicht dynamische) Klassen hinzufügen, verfügen Sie über Funktionen, die von Natur aus an eine Instanz gebunden sind , nicht nur an die Klasse selbst. Dies wirft ein paar Falten in die Spezifikation Function.apply, die ich ehrlich gesagt nicht untersucht habe, um herauszufinden, wie sie damit umgegangen sind.

Nicole
quelle
3
"Die Einbeziehung erstklassiger Funktionen selbst macht eine Sprache mehr oder weniger funktionsfähig." - Falsch. Es ist eine Voraussetzung, ja. Aber es steckt noch viel mehr dahinter, wie (um nur drei zu nennen) den veränderlichen Zustand zu vermeiden, sich auf Ausdrücke und Funktionsanwendungen zu konzentrieren und nicht auf sequentielle Anweisungen und die Betonung auf referenzielle Transparenz.
@delnan Dann solltest du Wikipedia korrigieren ... Es sei denn, eine "funktionale Sprache" und eine "Sprache, die ein funktionales Paradigma unterstützt" sind zwei verschiedene Dinge.
Nicole
1
@ Rensis: Das sind verschiedene Dinge. Sie können in C so etwas wie Objekte (sogar einschließlich vtables) erstellen, aber es ist nicht schön. Von "hat erstklassige Funktionen" zu "ist eine funktionale Sprache" zu wechseln ist nicht ganz so schlimm, aber es ist immer noch ein Unterschied. Außerdem gibt das Wiki (korrekt) auf der Seite an, auf die Sie verlinkt haben: "Diese Funktionen sind eine Notwendigkeit für den funktionalen Programmierstil [...]." (dh: nicht "das definierende Merkmal") und listet mehrere andere Merkmale auf der Seite auf FP auf.
@delnan, Okay, ich habe meinen Wortlaut korrigiert. Ich meinte nur die Bedingung, dass eine Sprache ein funktionales Paradigma unterstützt - ebenso wie die Wikipedia-Seite für jede der von mir aufgelisteten Sprachen. Ich wollte nicht sagen, dass das alles ist, was Teil des funktionalen Programmierstils ist .
Nicole
0

Ich habe mich das gleiche gefragt. Sobald ich in einer Sprache mit Lambdas bin, benutze ich sie VIEL. Sogar PHP wird besser, wenn Sie feststellen, dass Sie mit PHP 5.3 einen Abschluss machen können (es ist nicht so schön wie Lisp, aber immer noch besser).

Zachary K.
quelle