Ich habe in letzter Zeit viel darüber nachgedacht, wie man funktionale Programmierung in C ( nicht in C ++) durchführt. Offensichtlich ist C eine prozedurale Sprache und unterstützt die funktionale Programmierung von Haus aus nicht wirklich.
Gibt es Compiler- / Spracherweiterungen, die der Sprache einige funktionale Programmierkonstrukte hinzufügen? GCC bietet verschachtelte Funktionen als Spracherweiterung. Verschachtelte Funktionen können auf Variablen aus dem übergeordneten Stapelrahmen zugreifen, dies ist jedoch noch weit von ausgereiften Abschlüssen entfernt.
Eine Sache, die meiner Meinung nach in C wirklich nützlich sein könnte, ist, dass Sie überall dort, wo ein Funktionszeiger erwartet wird, einen Lambda-Ausdruck übergeben können, wodurch ein Abschluss erstellt wird, der in einen Funktionszeiger zerfällt. C ++ 0x wird Lambda-Ausdrücke enthalten (was ich großartig finde); Ich suche jedoch nach Werkzeugen für Straight C.
[Bearbeiten] Zur Verdeutlichung versuche ich nicht, ein bestimmtes Problem in C zu lösen, das für die funktionale Programmierung besser geeignet wäre. Ich bin nur neugierig, welche Tools es gibt, wenn ich das wollte.
quelle
Antworten:
Mit FFCALL können Sie Abschlüsse in C erstellen -
callback = alloc_callback(&function, data)
gibt einen Funktionszeiger zurück, dercallback(arg1, ...)
dem Aufruf entsprichtfunction(data, arg1, ...)
. Sie müssen die Speicherbereinigung jedoch manuell durchführen.In ähnlicher Weise wurden Blöcke zu Apples GCC-Gabel hinzugefügt. Sie sind keine Funktionszeiger, aber Sie können Lambdas weitergeben, ohne dass Speicher für erfasste Variablen von Hand erstellt und freigegeben werden müssen (effektiv werden einige Kopier- und Referenzzählungen durchgeführt, die sich hinter einigen syntaktischen Zucker- und Laufzeitbibliotheken verbergen).
quelle
Sie können die verschachtelten Funktionen von GCC verwenden, um Lambda-Ausdrücke zu simulieren. Tatsächlich habe ich ein Makro, das dies für mich erledigt:
Verwenden Sie wie folgt:
quelle
__fn__
nur ein beliebiger Name für die im Block definierte Funktion zu sein({
...})
nicht eine GCC-Erweiterung oder ein vordefiniertes Makro? Die Wahl des Namens für__fn__
(der der GCC-Definition sehr ähnlich sieht) hat mich wirklich am Kopf kratzen lassen und die GCC-Dokumentation nach keinem guten Effekt durchsucht.Bei der funktionalen Programmierung geht es nicht um Lambdas, sondern um reine Funktionen. Folgendes fördert also allgemein den funktionalen Stil:
Verwenden Sie nur Funktionsargumente, keinen globalen Status.
Minimieren Sie Nebenwirkungen, z. B. printf oder E / A. Rückgabedaten, die E / A beschreiben und ausgeführt werden können, anstatt die Nebenwirkungen direkt in allen Funktionen zu verursachen.
Dies kann in der Ebene c erreicht werden, ohne dass Magie erforderlich ist.
quelle
map
wenn man nicht die Möglichkeit hat, eine Funktion an sie zu übergeben?Hartel & Mullers Buch Functional C ist heutzutage (2012-01-02) unter folgender Adresse zu finden: http://eprints.eemcs.utwente.nl/1077/ (es gibt einen Link zur PDF-Version).
quelle
Voraussetzung für einen funktionalen Programmierstil ist eine erstklassige Funktion. Es könnte in tragbarem C simuliert werden, wenn Sie Folgendes tolerieren:
Die Laufzeit für einen solchen Code kann so klein wie die folgende sein
Im Wesentlichen ahmen wir erstklassige Funktionen mit Abschlüssen nach, die als Paar von Funktionen / Argumenten plus Makros dargestellt werden. Den vollständigen Code finden Sie hier .
quelle
Die Hauptsache, die mir in den Sinn kommt, ist die Verwendung von Codegeneratoren. Wären Sie bereit, in einer anderen Sprache zu programmieren, die die funktionale Programmierung bereitstellt, und daraus den C-Code zu generieren?
Wenn dies keine attraktive Option ist, können Sie CPP missbrauchen, um einen Teil des Weges dorthin zu finden. Mit dem Makrosystem sollten Sie einige funktionale Programmierideen emulieren können. Ich habe gehört, dass gcc auf diese Weise implementiert ist, aber ich habe es nie überprüft.
C kann natürlich Funktionen mithilfe von Funktionszeigern weitergeben, die Hauptprobleme sind fehlende Verschlüsse und das Typsystem neigt dazu, im Weg zu sein. Sie könnten leistungsfähigere Makrosysteme als CPP wie M4 untersuchen. Ich denke letztendlich, was ich vorschlage, ist, dass wahres C der Aufgabe nicht ohne großen Aufwand gewachsen ist, aber Sie könnten C erweitern, um es der Aufgabe gewachsen zu machen. Diese Erweiterung würde C am ähnlichsten aussehen, wenn Sie CPP verwenden oder zum anderen Ende des Spektrums gehen und C-Code aus einer anderen Sprache generieren könnten.
quelle
Wenn Sie Closures implementieren möchten, müssen Sie sich mit Assemblersprache und Stack Swapping / Management vertraut machen. Ich empfehle nicht dagegen, sondern sage nur, dass Sie das tun müssen.
Sie sind sich nicht sicher, wie Sie mit anonymen Funktionen in C umgehen sollen. Auf einem von Neumann-Computer können Sie jedoch anonyme Funktionen in asm ausführen.
quelle
Schauen Sie sich Hartel & Mullers Buch Functional C an
http://www.ub.utwente.nl/webdocs/ctit/1/00000084.pdf
http://www.cs.bris.ac.uk/~henkm/f2c/index.html
quelle
Die Felix-Sprache wird in C ++ kompiliert. Vielleicht könnte das ein Sprungbrett sein, wenn Ihnen C ++ nichts ausmacht.
quelle
Nun, einige Programmiersprachen sind in C geschrieben. Einige von ihnen unterstützen Funktionen als erstklassige Bürger. Sprachen in diesem Bereich sind ecl (eingebettetes Common Lisp IIRC), Gnu Smalltalk (gst) (Smalltalk hat Blöcke), dann gibt es Bibliotheken für "Verschlüsse" zB in glib2 http://library.gnome.org/devel/gobject/unstable/chapter-signal.html#closure, die zumindest in die Nähe der funktionalen Programmierung kamen. Vielleicht ist die Verwendung einiger dieser Implementierungen für die funktionale Programmierung eine Option.
Na oder du kannst Ocaml, Haskell, Mozart / Oz oder ähnliches lernen ;-)
Grüße
quelle
Die Art und Weise, wie ich funktionale Programmierung in C durchführte, bestand darin, einen funktionalen Sprachinterpreter in C zu schreiben. Ich nannte ihn Fexl, was für "Function EXpression Language" steht.
Der Interpreter ist sehr klein und kompiliert auf meinem System mit aktiviertem -O3 auf 68 KB. Es ist auch kein Spielzeug - ich verwende es für den gesamten neuen Produktionscode, den ich für mein Unternehmen schreibe (webbasierte Buchhaltung für Investitionspartnerschaften).
Jetzt schreibe ich C-Code nur, um (1) eine integrierte Funktion hinzuzufügen, die eine Systemroutine aufruft (z. B. Fork, Exec, Setrlimit usw.), oder (2) eine Funktion zu optimieren, die sonst in Fexl geschrieben werden könnte (z. B. Suche) für einen Teilstring).
Der Modulmechanismus basiert auf dem Konzept eines "Kontextes". Ein Kontext ist eine Funktion (in Fexl geschrieben), die ein Symbol seiner Definition zuordnet. Wenn Sie eine Fexl-Datei lesen, können Sie sie in einem beliebigen Kontext auflösen. Auf diese Weise können Sie benutzerdefinierte Umgebungen erstellen oder Code in einer eingeschränkten "Sandbox" ausführen.
http://fexl.com
quelle
Was ist an C, das Sie funktionsfähig machen möchten, die Syntax oder die Semantik? Die Semantik der funktionalen Programmierung könnte sicherlich zum C-Compiler hinzugefügt werden, aber wenn Sie fertig sind, haben Sie im Wesentlichen das Äquivalent einer der vorhandenen funktionalen Sprachen wie Schema, Haskell usw.
Es wäre besser, die Zeit zu nutzen, um nur die Syntax der Sprachen zu lernen, die diese Semantik direkt unterstützen.
quelle
Ich weiß nichts über C. Es gibt einige funktionale Funktionen in Objective-C, GCC unter OSX unterstützt jedoch auch einige Funktionen. Ich würde jedoch erneut empfehlen, eine funktionale Sprache zu verwenden. Es gibt viele, die oben erwähnt wurden. Ich persönlich habe mit Schema begonnen, es gibt einige ausgezeichnete Bücher wie The Little Schemer, die Ihnen dabei helfen können.
quelle