Wie funktional ist C++11?



  • ipsec schrieb:

    Wäre die Frage "ist C++ eine funktionale Programmiersprache", wäre die Antwort ganz klar nein.

    Wie ihr alle Unrecht habt!
    Die Antwort ist ganz klar ja:

    <a href= schrieb:

    C++-Artikel in Wikipedia">Paradigmen: Multiparadigmen (imperativ, strukturiert, objektorientiert, generisch, funktional)

    </ironie>

    hustbaer schrieb:

    "Wie funktional ist C++" ist klar eine Checkboxen-Frage (mit "analogen Checkboxen", hihi), die Antwort "gar nicht" wäre daher falsch.

    Gut. Und was ist die Antwort auf "Wie funktional ist Assembler"? C++-Code macht das gleiche wie Assemblercode, also ist Assembler funktional. Und Brainfuck? Analog dazu ebenfalls funktional. Du kannst das für jede Sprache machen, die nur turing-vollständig ist. Wenn du mir folgen konntest, dann sag mir: Gibt es eine turing-vollständige Sprache, die irgendein Programmierparadigma (das von einer anderen turing-vollständigen Sprache unterstützt wird) nicht erlaubt? Nein.

    Das Problem ist, dass je nach dem, wie man den Begriff Paradigma versteht, eine andere Antwort herauskommt.

    Wenn man das Wort so versteht, wie es in der englischen Wikipedia steht, ein fundamentaler Programmierstil, dann muss man sagen: C++ kann funktional sein, aber der Stil ist nicht fundamental in der Sprache verankert. Daher gehört in der Checkbox ein "gar nicht" hin und der Eintrag in der – wohlgemerkt deutschen – Wikipedia gehört raus.



  • @Zeus:
    Tut mir leid, aber den Satz verstehe ich nicht 😕



  • Tyr schrieb:

    Die Antwort ist ganz klar ja:

    <a href= schrieb:

    C++-Artikel in Wikipedia">Paradigmen: Multiparadigmen (imperativ, strukturiert, objektorientiert, generisch, funktional)

    Im englischen Artikel dazu ist das nicht vermerkt. Und er ueberrascht micht auf der deutschen Seite. Die Diskussion zu diesem Punkt laesst vermuten, dass funktional besser weggelassen werden sollte.

    Leider macht sich kaum jemand ausser mir die Muehe darzustellen, was er unter funktional versteht. Ich beziehe mich der Einfachheit halber auf:

    programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data

    Durch die Anlehnung an mathematische Funktionen kann ich den Wert eines Ausdrucks durch sukzessive Substitution ermitteln. In imperativen Sprachen wie C++ ist das nicht moeglich, da ich nur Befehle oder Instruktionen substituieren kann, aber der Wert eines Ausdrucks nur durch die Abarbeitung der Instruktionen ermittelt werden kann.

    Gehen wir weiter zu map, filter und fold und schauen uns diese in C++ an: http://www.cplusplus.com/reference/std/numeric/accumulate/ . Zeile 5: Zuweisung, also Zustandsaenderung! Dabei haben wir die Sprachebene von C++ nicht verlassen. Zwar wird fuer map, filter und fold in funktionalen Sprachen wie SML sicher auch das Assembleraequivalent einer Schleife generiert, doch wird dabei die Sprachebene von SML verlassen. Grund dafuer ist die vorherrschende Rechnerachitektur.

    Fazit: Auch wenn Closures oder funktionen hoeherer Ordnung Elemente der Sprache sind, heisst das noch lange nicht, dass die Sprache das funktionale Programmierparadigma unterstuetzt.

    der/das Schild

    An sowas habe ich auch schon gedacht und lasse mich gern belehren. Also der Kalkuel.

    Es basiert nur oberflächlich darauf. Er hat sich inspirieren lassen, es aber nicht richtig umgesetzt.

    Ich gebe dir recht. Lisp ist sowieso so eine Sache und wird von Lispern nicht als funktionale Sprache angesehen.



  • knivil schrieb:

    Im englischen Artikel dazu ist das nicht vermerkt.

    Dann wirds aber Zeit.



  • Fazit: Auch wenn Closures oder funktionen hoeherer Ordnung Elemente der Sprache sind, heisst das noch lange nicht, dass die Sprache das funktionale Programmierparadigma unterstuetzt.

    Natürlich unterstützt sie es.
    Es ist nur in C++ wesentlich einfacher auszubrechen als in anderen funktionalen Sprachen.
    Wenn man sich strikt nach "avoids state and mutable data" richtet, bleiben kaum mehr Sprachen übrig. Alle praktikablen funktionalen Sprachen erlauben das auf die eine oder andere Weise.



  • Tyr schrieb:

    C++-Code macht das gleiche wie Assemblercode, also ist Assembler funktional.

    Das ist ja mal Quatsch. Beim Paradigma geht es doch nicht um die Mächtigkeit, sondern, ich wiederhole mich, um den Stil. Mit Assembler bekommt man keinen funktionalen Stil hin, mit C++ schon. Also unterstützt C++ das funktionale Programmierparadigma, aber da wie du sagtest dieses nicht fundamental in der Sprache verankert ist, ist C++ keine funktionale Programmiersprache.

    knivil schrieb:

    Gehen wir weiter zu map, filter und fold und schauen uns diese in C++ an: http://www.cplusplus.com/reference/std/numeric/accumulate/ . Zeile 5: Zuweisung, also Zustandsaenderung!

    Na und? C++ erzwingt funktionale Programmierung nicht. Hier wäre eine funktionale Version von accumulate:

    template <class InputIterator, class T>
       T accumulate ( InputIterator first, InputIterator last, T init )
    {
        return first == last ? init : *first + accumulate(next(first), last, init);
    }
    

    next bekommst du wahrscheinlich allgemein nicht ohne Seiteneffekte hin, das liegt aber nicht an C++, sondern am Konzept der Iteratoren.

    Die Rekursion natürlich auch das Problem des evntl. Stackoverflows, für den funktionalen Stil spielt das aber keine Rolle (das ist auch ein Kompromiss, den man in C++ eingehen muss, weshalb man nahezu immer die imperative Variante mit der Schleife wählen wird - aber wenn man will, kann man).



  • ipsec schrieb:

    Na und? C++ erzwingt funktionale Programmierung nicht. Hier wäre eine funktionale Version von accumulate:

    template <class InputIterator, class T>
       T accumulate ( InputIterator first, InputIterator last, T init )
    {
        return first == last ? init : *first + accumulate(next(first), last, init);
    }
    

    Also ist C++ funktional, weil in C++ StatementExpr unterstützt ? Ein anderen Sinn seh ich in diesen Beispiel nicht.

    btw ich finds intressent dass die Leute sagen, C++ ist funktional dies anhand sehr konkreten Stellen machen während die es nicht, nur eine Leitsatz zu hand haben um dies zu entscheiden.



  • Zeus schrieb:

    ipsec schrieb:

    Na und? C++ erzwingt funktionale Programmierung nicht. Hier wäre eine funktionale Version von accumulate:

    template <class InputIterator, class T>
       T accumulate ( InputIterator first, InputIterator last, T init )
    {
        return first == last ? init : *first + accumulate(next(first), last, init);
    }
    

    Also ist C++ funktional, weil in C++ StatementExpr unterstützt ? Ein anderen Sinn seh ich in diesen Beispiel nicht.

    btw ich finds intressent dass die Leute sagen, C++ ist funktional dies anhand sehr konkreten Stellen machen während die es nicht, nur eine Leitsatz zu hand haben um dies zu entscheiden.

    Der Sinn des Beispiels: nur weil auf c-plusplus.com/reference eine imperative Implementierung von accumulate steht, heißt das keineswegs, dass man es nicht auch funktional implementeiren kann.
    Hast du irgendeinen Algorithmus, der in C++ nicht funktional zu implementieren geht?



  • ipsec schrieb:

    Hast du irgendeinen Algorithmus, der in C++ nicht funktional zu implementieren geht?

    Du weiß ganz genau, dass wegen den nicht obligatorischen Tail-Recursion Optimierung die einfachsten mathematische Funktionen nicht portable genug sind um sie funktional implementiert bereitzustellen.



  • Zeus schrieb:

    ipsec schrieb:

    Hast du irgendeinen Algorithmus, der in C++ nicht funktional zu implementieren geht?

    Du weiß ganz genau, dass wegen den nicht obligatorischen Tail-Recursion Optimierung die einfachsten mathematische Funktionen nicht portable genug sind um sie funktional implementiert bereitzustellen.

    Damit ist nur gesagt, dass es nicht sinnvoll ist, in C++ funktional zu programmieren (dem stimme ich auch zu), aber nicht, dass es nicht ginge.



  • ipsec schrieb:

    Zeus schrieb:

    ipsec schrieb:

    Hast du irgendeinen Algorithmus, der in C++ nicht funktional zu implementieren geht?

    Du weiß ganz genau, dass wegen den nicht obligatorischen Tail-Recursion Optimierung die einfachsten mathematische Funktionen nicht portable genug sind um sie funktional implementiert bereitzustellen.

    Damit ist nur gesagt, dass es nicht sinnvoll ist, in C++ funktional zu programmieren (dem stimme ich auch zu), aber nicht, dass es nicht ginge.

    Damit werden wir nie Grün, weil das Paradigma ein Leitgedanke ist, dass du nicht anhand von detailierten Kleinkram festmachen kannst.



  • Zeus schrieb:

    btw ich finds intressent dass die Leute sagen, C++ ist funktional dies anhand sehr konkreten Stellen machen während die es nicht, nur eine Leitsatz zu hand haben um dies zu entscheiden.

    Du findest meine Argumentation schlecht? Was sollte ich denn verbessern?

    Angenommen Closures und Funktionen hoeherer Ordnung sind einziges Kriterium. In C++ sind Closures und Funktionen hoeherer Ordnung im Vergleich zu funktionalen Sprachen sehr, sehr beschraenkt. Also unterstuetzt C++ das funktionale Programmierparadigma sehr, sehr beschraenkt.

    heißt das keineswegs, dass man es nicht auch funktional implementeiren kann

    Aber darum geht es nicht. Es geht nicht darum was so alles moeglich ist, sondern in wiefern mich die Sprache unterstuetzt. Was also wirklich gemacht wird. Schauen wir uns doch mal die STL an. Alle Datenstrukturen sind mit Seiteneffekten behaftet. avoids mutable state/data ? Selbst das Minibeispiel accumulate macht Schwierigkeiten. Um funktional zu sein, muss ich in C++ ziemlich viel ignorieren/wegschmeissen und neu implementieren. Klar ist das moeglich, aber das nennst du Unterstuetzung? Quatsch!

    dass es nicht sinnvoll ist, in C++ funktional zu programmieren

    Genau deswegen unterstuetzt C++ nicht das funktionale Programmierparadigma.



  • knivil schrieb:

    Angenommen Closures und Funktionen hoeherer Ordnung sind einziges Kriterium. In C++ sind Closures und Funktionen hoeherer Ordnung im Vergleich zu funktionalen Sprachen sehr, sehr beschraenkt. Also unterstuetzt C++ das funktionale Programmierparadigma sehr, sehr beschraenkt.

    Das ist ja schonmal besser als "gar nicht" 👍

    Um funktional zu sein, muss ich in C++ ziemlich viel ignorieren/wegschmeissen und neu implementieren.

    Oder vom funktionalen Paradigma Dinge weglassen.



  • knivil schrieb:

    Zeus schrieb:

    btw ich finds intressent dass die Leute sagen, C++ ist funktional dies anhand sehr konkreten Stellen machen während die es nicht, nur eine Leitsatz zu hand haben um dies zu entscheiden.

    Du findest meine Argumentation schlecht? Was sollte ich denn verbessern?

    Eigentlich dachte wir sind im selben Boot.



  • Zeus schrieb:

    Eigentlich dachte wir sind im selben Boot.

    Dachte ich auch! 🙂



  • Zeus schrieb:

    ipsec schrieb:

    Hast du irgendeinen Algorithmus, der in C++ nicht funktional zu implementieren geht?

    Du weiß ganz genau, dass wegen den nicht obligatorischen Tail-Recursion Optimierung die einfachsten mathematische Funktionen nicht portable genug sind um sie funktional implementiert bereitzustellen.

    Tail Call Optimization ist ein Compiler Problem, kein Sprachproblem.
    http://drdobbs.com/184401756

    Moderne Compiler koennen teilweise Tail Call Optimization. Es ist in C++ halt ein komplexes Thema und bringt nahezu nie etwas, deshalb wird es nicht mit aller Kraft verfolgt.

    Beispiel:

    int add(int a, int b) {
    	if (b == 0)
    		return a;
    	return add(1 + a, b - 1);
    }
    

    Das macht mein VC++ zu

    PUBLIC	_add
    ; Function compile flags: /Ogtpy
    ; File d:\code\tailrecursiontest\tailrecursiontest\main.c
    _TEXT	SEGMENT
    _a$ = 8							; size = 4
    _b$ = 12						; size = 4
    _add	PROC
    
    ; 24   : 	if (b == 0)
    ; 25   : 		return a;
    ; 26   : 	return add(1 + a, b - 1);
    
    	mov	eax, DWORD PTR _a$[esp-4]
    	mov	ecx, DWORD PTR _b$[esp-4]
    	inc	eax
    	dec	ecx
    	je	SHORT $LN8@add
    	mov	DWORD PTR _b$[esp-4], ecx
    	mov	DWORD PTR _a$[esp-4], eax
    	jmp	_add
    $LN8@add:
    
    ; 27   : }
    
    	ret	0
    

    Also ist C++ jetzt funktional weil wir Tail Call Optimzation haben?



  • int add(int a, int b) {
        if (b == 0)
            return a;
        return add(1 + a, b - 1);
    }
    

    macht gcc 4.5 (mingw) mit -O3 -march=native auf AMD Sempron 3000+ zu

    pushl	%ebp
    	movl	%esp, %ebp
    	movl	8(%ebp), %eax
    	addl	12(%ebp), %eax
    	leave
    	ret
    

    Also ist C++ funktional. 🤡 🤡 🤡



  • wer beid en gcc entwicklern hat denn denkzeit darauf verschwendet, SOWAS bis zum letzten Takt zu optimieren? wtf?



  • Der Optimizer von GCC macht mir Angst 😞


Anmelden zum Antworten