Können Sie funktionale Programmierung in C lernen? [geschlossen]


9

Als Ergebnis der Kommentardiskussion hier frage ich mich, ob Sie funktionale Programmierung in C lernen können.


30
Unabhängig davon, ob Sie können oder nicht, sollten Sie nicht .
R. Martinho Fernandes

27
Absolut! Der erste Schritt ist, einen Lisp-Dolmetscher zu schreiben ;-)
Ferruccio

Wenn ich es richtig verstanden hätte, hätte die Frage lauten sollen, verschiedene Konzepte mit Pseudocode zu lernen, ohne überhaupt eine echte Sprache.
SK-Logik

@ SK-Logik: Um es milde auszudrücken, nur sehr wenige Programmierer haben das Programmieren nur mit Pseudocode gelernt, die meisten mussten sich die Hände schmutzig machen und ihre Gesichter mit Fehlermeldungen vom Compiler / Interpreter schlagen.
sbi

4
@sbi, einige der besten Programmierer haben das Programmieren gelernt, als Compiler überhaupt keine Fehlermeldungen hatten. Das Codieren auf Lochkarten erfordert ein wenig Verständnis dafür, was Sie tun, lange bevor Sie die Möglichkeit haben, den Code auszuführen. Und natürlich war die Basis für die funktionale Programmierung lange vor dem Bau eines ersten Computers geschaffen worden.
SK-Logik

Antworten:


21

Natürlich können Sie funktionale Programmierung in C durchführen. Theoretisch können Sie auch funktionale Programmierprinzipien in C lernen , aber die Sprache macht es nicht einfach.

Ich gehe davon aus, dass Sie zumindest ein wenig Hintergrundwissen in OOP haben. Wenn Sie dies tun, sollten Sie sich darüber im Klaren sein, dass OOP in C durchgeführt werden kann, einschließlich Polymorphismus, Getter / Setter, Sichtbarkeitsregeln usw. usw., aber es ist ziemlich schmerzhaft, dies zu tun, und Sie müssen sowohl OOP als auch C im Inneren kennen. herausziehen. Bei FP ist es ähnlich.

Was Sie tun sollten , ist zuerst eine funktionale Programmiersprache zu lernen (die meisten von ihnen haben überraschend einfache Syntaxregeln; es ist nicht die Syntax, die sie schwer zu erlernen macht) und dann Ihre neu erworbene Weisheit die Art und Weise beeinflussen zu lassen, wie Sie C schreiben.


Auf Anfrage können Sie einige Dinge von FP lernen und dann beispielsweise in C, C ++ oder Java anwenden:

  • Vermeiden Sie den Status, insbesondere den gemeinsam genutzten veränderlichen Status
  • Schätzen Sie reine Funktionen
  • Schätzen Sie die faule Bewertung
  • In der Lage sein, eher anhand von Verben als anhand von Substantiven zu modellieren
  • Probleme sowohl rekursiv als auch iterativ angehen zu können
  • Funktionen höherer Ordnung verwenden
  • Stellen Sie sich Funktionen als eine andere Art von Wert vor, den Sie weitergeben und mit anderen Werten kombinieren können
  • Verwendung erstklassiger Funktionen als Alternative für objektbasierten Polymorphismus

1
Können Sie konkrete Beispiele dafür liefern, wie C / C ++ / Java-Programmierer von der LISP-Weisheit profitieren können? Theoretisch macht es Sinn, aber ich suche etwas Konkretes.
Job

@Job, Welchen konkreten Nutzen kann es geben? Es erweitert ihren Geist und lässt sie vielleicht einen übermäßigen veränderlichen Zustand als eine schlechte Sache betrachten. Was könnte man mehr verlangen?
dan_waterworth

Kann ich daraus schließen, dass es zwar möglich ist, (einige) FP in C zu lernen, dies aber keinen Sinn macht?
sbi

@Job: Ich habe FP gelernt, als ich vor vielen Jahren als Student LISP gelernt habe. Ungefähr ein Jahrzehnt später habe ich FP in der Template-Meta-Programmierung angewendet.
sbi

1
@sbi, meine Lieblingsmethode zum Erlernen neuer Sprachen und Konzepte ist die Implementierung. Und C ist eine recht anständige Sprache für die Implementierung eines Compilers. Also, ja, Sie können FP mit C lernen.
SK-Logik

11

C kann gehackt werden, um einige funktionale Konzepte anzubieten:

Diese StackOverflow-Frage sagt Ihnen mehr. Obwohl es möglich zu sein scheint, funktionale Programmierung (oder eine große Teilmenge davon) in C durchzuführen, sind Hacks und Compiler-Erweiterungen und was auch immer nicht der beste Weg, um ein Konzept kennenzulernen.

Um funktionales Programmieren tatsächlich zu lernen, ist eine der bekanntesten funktionalen Programmiersprachen wie Lisp und seine Dialekte ( Clojure , Scheme ), Erlang und Haskell die beste Wahl . Jedes dieser Tools ist perfekt, um innerhalb der Denkweise der funktionalen Programmierung zu arbeiten. F # ist auch ein guter Kandidat, wenn Sie einen .Net-Hintergrund haben, aber es ist eine Multi-Paradigmen-Sprache, nicht ausschließlich eine funktionale Programmiersprache.


Wie tdammers in den Kommentaren feststellt:

Tatsächlich sind LISP, Clojure und Schema auch Multi-Paradigmen. Haskell ist zwar rein und standardmäßig faul, ermöglicht jedoch auch eine zwingende Programmierung in einem monadischen Kontext und bietet umfassende Unterstützung für die gleichzeitige Verarbeitung. Alle diese Mechanismen verfügen über Mechanismen, die große Teile der in der OOP-Welt gesammelten Weisheit umsetzen - Kapselung, Vererbung, Einzelverantwortung, Zusammensetzung usw. Es geht nicht so sehr darum, ob eine Sprache andere Paradigmen zulässt. Es geht darum, welches Paradigma den Ausgangspunkt einer Sprache bildet.

Nach meinem besten Wissen sind Lisp und seine Dialekte und Erlang bessere Kandidaten als F #, weil sie die funktionale Programmierung gegenüber anderen Paradigmen fördern , was tdammers wunderbar als Ausgangspunkt einer Sprache angibt . F # umfasst funktionale Programmierung, ermutigt sie jedoch nicht gegenüber anderen unterstützten Paradigmen, der imperativen und der oo-Programmierung.


Zu Ihrem letzten Satz: In diesem Fall würde ich argumentieren, dass F # ein besserer Kandidat ist, weil es Sie nicht in einer funktionalen Denkweise gefangen hält. In einer Multi-Paradigmen-Sprache können Sie, wenn Sie mit dem Hämmern von Schrauben beginnen, einfach zu einem Schraubendreher wechseln. Wenn Sie in einem einzigen Paradigma gefangen sind, können Sie den Unterschied zwischen der Schraube und dem Nagel übersehen.
R. Martinho Fernandes

Nun, die Frage ist, wie man funktionale Programmierung lernt, nicht Programmierung. Ich gehe davon aus, dass die Operation Erfahrung in einer Multi-Paradigmen-Sprache hat und den effizientesten Weg zum Erlernen der funktionalen Programmierung sucht. In diesem Fall ist F # ein guter Kandidat, aber kein perfekter. Gefangen in einem einzigen Paradigma ist offensichtlich der beste Weg, wenn Sie dieses einzelne Paradigma kennenlernen möchten, da Sie sich nicht mit allem befassen müssen, was es nicht ist.
Yannis

Ich glaube, dass das Lernen, wenn das Paradigma gut geeignet ist und wenn es für eine bestimmte Aufgabe nicht geeignet ist, ein Teil des Lernens ist, vielleicht das wichtigste.
R. Martinho Fernandes

4
Tatsächlich sind LISP, Clojure und Schema auch Multi-Paradigmen. Haskell ist zwar rein und standardmäßig faul, ermöglicht jedoch auch eine zwingende Programmierung in einem monadischen Kontext und bietet umfassende Unterstützung für die gleichzeitige Verarbeitung. Alle diese Mechanismen verfügen über Mechanismen, die große Teile der in der OOP-Welt gesammelten Weisheit umsetzen - Kapselung, Vererbung, Einzelverantwortung, Zusammensetzung usw. Es geht nicht so sehr darum, ob eine Sprache andere Paradigmen zulässt. Es geht darum, welches Paradigma den Ausgangspunkt einer Sprache bildet.
tdammers

2
@ MartinhoFernandes: Man könnte argumentieren, dass in einem einzigen Paradigma gefangen zu sein der perfekte Weg ist, um zu lernen, wenn es wirklich ein Schmerz im Arsch ist :-)
Jörg W Mittag


2

TL; DR

Bei der funktionalen Programmierung geht es um Verschlüsse und deren Anwendungen. Vergessen Sie die Verwendung von C, um die funktionale Programmierung zu erlernen, es sei denn, jemand kann Ihnen eine Abstiegsschließungsbibliothek für C zeigen.

Was ist funktionale Programmierung?

Das Hauptkonzept der funktionalen Programmierung ist der Begriff der Verschlüsse, der grob gesagt eine Funktion zusammen mit Variablenbindungen erfasst. Neben der allgegenwärtigen Verwendung von Verschlüssen gibt es einige andere charakteristische Merkmale in der funktionalen Programmierung, wie die Verwendung von rekursiven Funktionen und unveränderlichen Werten (beide spielen gut zusammen). Diese Merkmale sind mehr ein kulturelles Problem als alles andere, und es gibt kein technisches Hindernis, sie in praktisch jeder Sprache zu verwenden. Deshalb konzentriere ich mich in meiner Antwort auf Verschlüsse: Nicht jede Sprache erlaubt es, einfach Verschlüsse zu erstellen.

Drei Abbildungen der Verwendbarkeit von Verschlüssen

Eine typische Verwendung von Schließungen ist die Implementierung von Datenschutzmechanismen. Zum Beispiel der Javascript-Code - in den Beispielen habe ich Javascript ausgewählt, weil es eine funktionale Sprache mit einer sogenannten „C-ähnlichen Syntax“ ist und Ihre Frage darauf hindeutet, dass Sie mit C vertraut sind:

create_counter = function()
{
  var x = 0;
  var counter = function()
  {
    ++x;
    return x;
  };
  return counter;
}

Dann mit

a = create_counter();
b = create_counter();

Wir haben zwei Funktionen aund bzählen disjunkte Sammlungen. Der Punkt des Beispiels ist, dass die Variablen xdurch den Abschluss erfasst werden, der den Abschluss definiert, counterund jedes Mal, wenn ein neuer counterAbschluss is instantiated by the function, it gets its fresh own idea of whatx` ist.

Eine andere typische Verwendung von Verschlüssen ist die Definition von Teilanwendungen von Funktionen. Angenommen, wir haben eine Berichtsfunktion, die der syslogImplementierung einer Funktion ähnelt

var log = function(priority, message) {

};

wo die Argumente priorityund messagevoraussichtlich Zeichenfolgen sind, wobei das erste eines von "debug"ist "info", und so weiter. Wir können eine Protokollfabrik wie folgt definieren:

var logWithPriority = function(priority) {
  return function(message) {
    log(priority, message);
  };
};

und verwenden Sie es, um spezielle Versionen unserer Protokollfunktion zu definieren:

var debug = logWithPriority("debug");
var info = logWithPriority("info");

Dies ist sehr nützlich, da anstatt fehleranfällige forSchleifen wie diese zu schreiben

for(i = 0; i < journal.length; ++i) {
   log("info", journal[i]);
}

wir können das sauberere, kürzere und viel einfachere schreiben (es gibt kein i, das ist viel besser):

journal.forEach(logWithPriority("info"));

Ein drittes wichtiges Anwendungsfeld von Schließungen ist die Implementierung einer verzögerten Evaluierung. Beachten Sie, dass eine spezielle Sprachunterstützung für eine bessere Implementierung sorgen kann.

Eine Lazy-Funktion gibt anstelle einer direkten Berechnung einen Abschluss zurück, der aufgerufen (oder im Jargon der Faulheit „gezwungen“) werden kann, um die Frage auszuführen. Die Motivation dafür ist, dass es die Vorbereitung einer Berechnung und die Durchführung einer Berechnung trennt. Ein praktisches Beispiel hierfür ist die Kompilierung regulärer Ausdrücke: Wenn ein Programm beim Start viele reguläre Ausdrücke kompiliert, benötigt es viel Zeit zum Starten. Wenn wir stattdessen die regulären Ausdrücke träge kompilieren und sie nach Bedarf erzwingen, kann unser Programm schnell gestartet werden. Natürlich können reguläre Ausdrücke hier durch jede Struktur ersetzt werden, die eine beträchtliche Initialisierungszeit erfordert.

Hier erfahren Sie, wie Sie eine verzögerte Auswertung mit Abschlüssen implementieren. Betrachten wir die klassische Umsetzung der arrayMax Funktion , um die Rückkehr max in einem Array:

function arrayMax(array) {
  return array.reduce(function(a, b) {
    return Math.min(a, b);
  };
}

Die faule Variante wäre:

function arrayMax(array) {
  var memo = null;
  function actuallyCompute() {
    if(memo === null) {
      memo = array.reduce(function(a, b) {
        return Math.min(a, b);
      });
    }
    return memo;
  }
  return actuallyCompute;
}

Der zurückgegebene Wert ist ein Abschluss, mit dem der Wert berechnet oder ein anderes Mal abgerufen werden kann, wenn er bereits berechnet wurde.

Mit diesen drei Beispielen sollten wir sicher sein, dass Verschlüsse und ihre Anwendungen den Kern der funktionalen Programmierung bilden.

Fazit

Das Erlernen der funktionalen Programmierung bedeutet das Erlernen des Programmierens mit Verschlüssen. Infolgedessen sollten Sprachen, die die einfache Manipulation von Verschlüssen und insbesondere die teilweise Anwendung von Funktionen ermöglichen, bei der Suche nach einer Sprache zum Studium der funktionalen Programmierung berücksichtigt werden. Umgekehrt wären Sprachen, in denen Schließungen nicht einfach manipuliert werden können, eine schlechte Wahl.


1
Danke für dieses schöne Beispiel. Übrigens, wenn Sie var info definieren, wäre es nicht journal.forEach (info)?
Ejaenv

Ja, es wäre eine passende Variante! :)
Michael Le Barbier Grünewald

1

Ich denke, dass die Werkzeuge, die Sie verwenden, Ihr Lernen stark beeinflussen. Es ist fast unmöglich, Programmierkonzepte zu lernen, für die die von Ihnen verwendete Programmiersprache nicht die Mittel bietet, die Sie verwenden können. Sicher, Sie können immer ein paar Dinge lernen, aber Sie können es nicht richtig lernen.

Aber das ist trotzdem akademisch, denn wie Martinho in seinem Kommentar sagt , sollten Sie nicht versuchen, dies zu tun , auch wenn Sie funktionale Programmierung lernen könnten , da es Sprachen gibt, in denen dies viel einfacher ist.


1

Sie sollten funktionale Programmierung nicht in C lernen, sondern in einer strengen funktionalen Sprache (Haskell, Caml, Erlang usw.)

Wenn Sie neu in der Funktion sind, werden Sie es nie wirklich mit einer nicht funktionalen Sprache bekommen. Wahrscheinlicher ist, dass Sie sich darin üben, das zu tun, was Sie für funktionale Programmierung halten, und die Dinge falsch lernen. Und es ist immer schwieriger, Dinge richtig neu zu lernen, als sie zuerst richtig zu lernen.

Wie auch immer, ich denke, funktional in C zu sein ist eine gute Übung für jemanden, der funktional bereits kennt. Weil diese Person lernen wird, was sich hinter der Haube abspielt - was der Computer wirklich tut.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.