was genau ist Functionale programmierung?



  • kingruedi schrieb:

    @Daniel E.
    also Lisp ist keine funktionelle Sprache, weil man damit auch anders programmieren kann? Dann ist ja O'Caml auch keine funktionelle Sprache (oder?)

    IMO kann man den Begriff funktional nicht sauber definieren. Die Abgrenzung ist keine Frage der An- bzw. Abwesenheit von Features, sondern wie sie designt sind und wie damit umgegangen wird. In SML ist die Zuweisung z.B. nur bei Referenzen erlaubt, und das Typsystem ist richtig ausgeklügelt, um die auftretenden Probleme irgendwie zu managen. In Lisp dagegen kannst du ohne weiteres loslegen und imperativ programmieren. Es ist dort eine reine Stilfrage, ob du z.B. Rekursion oder LOOP benutzt. Meistens entscheiden sich Entwickler für den imperativen Stil und flechten die funktionalen Teile (Lambda-Abstraktionen, Funktionen höherer Ordnung) nur dort ein, wo sie sinnvoll sind.

    BTW, "funktionell" heißt soweit ich weiß, dass etwas funktioniert 🙂



  • für welche art von aufgaben ist denn zb das lambda kalkül besonders geeignet? also bei welchen problemen ist diese progrmamierweise erste wahl? 🙂



  • wenn du eine Funktion dynamisch erzeugen willst oder nur eine kleine Funktion als Funktor irgend wo brauchst

    in Pseudo C++ Code

    std::find_if(vec.begin(),vec.end(),lambda<bool (int x)>{ return x==10; });
    

    oder

    typedef int (*ftor_t)(int);
    ftor_t foo(int j) {
      return lambda<int (int x)>{ return x*j; }
    }
    

    Lambda für C++ gibt es via Boost::Lambda.



  • Da könntest du genauso gut fragen, für welche Aufgaben man Turingmaschinen braucht 🙂 Der Lambda-Kalkül ist viel zu low-level für echte Programmierung.



  • Lambda für C++ gibt es via Boost::Lambda.

    oder gleich phönix aus spirit, die lib ist etwas weiter 🙂



  • Auch wenn es kein zwingendes Feature ist, bieten die modernen funktionalen Sprachen List Comprehension. Das ist so ungefähr die Mengenlehre angewnad auf verkettete Listen.

    Die meisten mir bekannten funktionalen Sprachen haben auch ein sehr mächtiges Typeinference-System (in C++ Type-Deduction genannt).

    Das nur um einige oft aufzufindende Merkmale zu nennen.



  • Ich habe in meiner letzten Antwort vergessen das Pattern-Matching (hat nix mit RegEx zu tun) zu erwähnen.

    Um einiges nochmal deutlicher zu machen:
    Funktionen werden wie Werte behandelt. Das Beudeutet ich kann Funktionen an andere Funktionen übergeben, welche zurückgeben und in der Regel auch welche "on the fly" generieren (Lambda-Ausdrücke, Funktions-Literale).

    Es gibt keine Seiteneffekte.
    Das Verändern des Wertes einer Variable ist beispielsweise ein Seiteneffekt. Deswegen ist in funktionalen Sprachen Rekursion auch eine extrem wichtige vorgehensweise, da Iteration prinzipiell auf Seiteneffekten basiert.

    Die Fakultät würde man in Haskell (eine rein funktionale Sprache) vermutlich so definieren (ich kann kaum Haskell):

    fakultaet 0 = 1
    fakultaet n = n * fakultaet (n - 1)
    

    Hier sieht man direkt das von mir oben genannte Pattern-Matching und die Rekursion.

    Um auch noch Funktionen höherer Ornung zu demonstrieren eine Funktion, die aus einer Liste eine neue generiert, bestehend aus den Elementen der Eingangsliste, auf die die übergebene Funktion angewendet wurde, folgendes:

    map funktion [] = []
    map funktion (head:tail) = funktion head : map funktion tail
    

    eine gemappte leere Liste ist eine leere Liste. Eine gemappte liste bestehend aus ihrem Kopf und den restlichen Elementen (ihrem Schwanz) ist die die Funktion angewand auf den Kopf und daran angehängt ein Rekursiver Aufruf auf den Schwanz.

    Und um auch noch die List Comprehension zu zeigen:

    map funktion list = [funktion element | element <- list]
    

    Eine gemappte Liste ist eine Liste auf deren Elemente die Funktion angewendet wurde.



  • Die Frage mach dem Sinn von funktionaler Programmierung ist die meistgestellte im ersten Semester Informatik.

    Laut Prof. Pepper (Pepper/funktionale Programmierung, ISBN 3-540-64541-1)
    "
    funktional:
    Ein Programm ist eine Ein-/Ausgaberelation, d.h., eie Abbildung von Eingabedaten auf zugehörige Ausgabedaten. Diese Abbildung wird im Programmtext direkt (als Funktion) hingeschrieben.
    imperativ:
    Ein Ptogramm ist eine Arbeitsanweisung für eine Maschine. Als "Nebenprodukt" ihrer Arbeit liefert diese Maschine zu den gegebenen eingabedaten die zugehörigen Ausgabedaten. Das Ein-/Ausgabeverhalten lässt sich anhand der Arbeitsweise der Maschine analysieren.

    funktional:
    Programme sind "zeilt-los". Eine Funktion wie zum Beispiel Sinus liefert Mittwoch die gleichen Ergebnisse wie am Donnerstag, vormittags die gleichen Zahlen wie nachmittags und im Winter nichts anderes als im Sommer.
    imperativ:
    Was ein Programmstück tut, hängt vom "Zustand" ab, in dem sich die ausführende Maschine gerade befindet, und dieser Zustand ändert sich im laufe der Zeit. Um ein Programm zu verstehen, muss man also immer seinen Ablauf inder Zeit "mitdenken".

    funktional:
    Die Formulierung von programmen findet auf einem recht abstrakten, mathematische orientierten Niveau statt.
    imperativ:
    Programme werden sehr konkret auf Maschinen bezogen formuliert, die Tätigkeit hat somit einen eher hantfesten, "handwerklichen" Charakter.

    funktional:
    Beispiele: LISP, ML, HASKEL, OPAL, MIRANDA usw.
    imperativ:
    Beispiele: ALGOL, FORTRAN, COBOL, PASCAL, C, C++, JAVA, SMALLTALK usw.
    "

    Ein weiterer Vorteil ist die tatsache, das in den meisten? funktionalen Sprachen Zahlen nicht als Konstanten abgebildet sind. Demnach gibt es auch kein maximum wie z.B in int aus C/C++. Es sind einfach ein paar wenige Konstanten definiert wie "1". "2" ist dann nachfolger(1);

    und ganz ehrlich, QuickSort in Opal sieht doch echt elegant aus:
    DEF sort(<>) == <>
    DEF sort(e :: Rest) == LET Small == sort(kleine(e,Rest))
    Medium == (e :: <>)
    Large == sort(grosse(e,Rest))
    IN
    sort(Small ++ Medium ++ Large)

    DEF kleine(_,<>) == <>
    DEF kleine(a,e,Rest) ==
    IF e <= a
    THEN e::kleine(a,rest)
    ELSE kleine(a,rest)
    FI

    DEF grosse(_,<>) == <>
    DEF grosse(a,e,Rest) ==
    IF e > a
    THEN e::grosse(a,rest)
    ELSE grosse(a,rest)
    FI



  • magheinz schrieb:

    Ein weiterer Vorteil ist die tatsache, das in den meisten? funktionalen Sprachen Zahlen nicht als Konstanten abgebildet sind. Demnach gibt es auch kein maximum wie z.B in int aus C/C++. Es sind einfach ein paar wenige Konstanten definiert wie "1". "2" ist dann nachfolger(1);

    Es würde mich wundern, wenn es auch nur eine einzige (ernstzunehmende, d.h. nicbt rein-akademische) funktionale Sprache gäbe, in der das stimmt.



  • und ganz ehrlich, QuickSort in Opal sieht doch echt elegant aus:

    Ist nicht gerade das eines DER Beispiele für Haskell und dort tausend mal schöner und verständlicher, als in Opal?

    quicksort []          = [] 
    quicksort (head:tail) = kleine ++ [head] ++ grosse
                            where kleine = quicksort [x | x <- tail, x < head] 
                                  grosse = quicksort [x | x <- tail, x >= head]
    

Anmelden zum Antworten