Diskussion:Funktionale Programmierung
Lokale Funktionsdefinitionen
BearbeitenSpeziell an funktionalen Sprachen ist unter anderem, dass hier lokale Funktionen definiert werden können, wie dies in imperativen Sprachen mit lokalen Variablen möglich ist.
- ist falsch, zwar in FORTRAN geht es nicht, aber in den Jahrzehnten danach ist es doch ziemlich allgemein möglich geworden Ptrs 00:14, 26. Apr 2003 (CEST)
- Sowohl Pascal (im Unterschied zu C) als auch Python unterstützen lokale Funktionen; beides sind imperative Sprachen. Ich glaube kaum, daß man so weit gehen kann, Pascal auch als funktionale Sprache zu bezeichnen, oder? --Tobias 18:43, 12. Jun. 2009 (CEST)
- Ich bin auch der Meinung, dass eine Charakterisierende Eigenschaften funktionaler Programmiersprachen die Tatsache ist, dass Funktionen Werte erster Ordnung sind (d.h. functions are first class values). Diese lassen sich meist auch in Form von Lambda Ausdrücken überall im Code (um genau zu sein, überall, wo Ausdrücke stehen können) definieren (und haben dann eventl. keinen Namen). Diese lokalen Funktionen haben dann die Möglichkeit, auf ihren statischen Kontext (d.h. die Varialben, die an der Stelle, an der die Funktion definiert wurde) zuzugreifen, auch wenn diese Funktionen dann z.B. mithilfe von Funktionsparametern an ganz andere Stelle des Programm ausgeführt werden. Diese Eigenschaft, dass die Funktionen zusammen mit Ihren Variablen an andere Funktionen übergeben werden, ist sehr zentral bei der Funktionalen Programmierung. Dies ist auch eine Ursache dafür, dass den Sprachen vorgeworfen wird, sie seien langsam. Denn das Verwalten der Closers ist nicht auf dem Stack möglich, wie bei imperativen Sprachen, sondern muss im Heap geschehen (oder man muss ne statische Analyse machen, wie das der Ocaml Compiler tut (deshalb ist Ocaml auch recht schnell im Vergleich zu anderen funktionalen Sprachen). Denn i.A. müssen die lokalen Variablen ja später noch zur Verfügung stehen). --Phillip 16:27, 28. Mai 2008 (CEST)
- In Python sind Funktionen First-class citizens (oder Bürger erster Klasse, Werte erster Ordnung, en:first-class objects, first-class values, Funktionen höherer Ordnung/„HOFs“, vollwertige Objekte …; in der deutschen Wikipedia gibt es offenbar leider noch keinen entsprechenden Artikel) und können zur Laufzeit aus dynamisch generiertem Code erzeugt werden. Ist Python also, als imperative Sprache mit funktionalen Elementen – Funktionsobjekte, einfache Lambda-Funktionen, die aus Haskell entlehnte Listennotation –, auch eine funktionale Programmiersprache? --Tobias 18:43 und 20:05, 12. Jun. 2009 (CEST)
Maple
BearbeitenFehlt hier nicht noch die Programmiersprache des Mathematik-Programms 'Maple'? --Mikroprozessor 20:01, 2. Apr 2005 (CEST)
- Nein. Die Maple-Programmiersprache hat soweit ich weiß Seiteneffekte und verletzt damit eine wichtige Eigenschaft funktionaler Sprachen, nämlich die Werttreue. --fschoenm 02:02, 3. Apr 2005 (CEST)
Auswertungsstrategie
BearbeitenÖh, hab mal bei der Auswertungsstrategie geändert. So wie unser Prof. uns das erklärt hat (und wie es im Skript seines Kollegen steht) ist Lazy-Evaluation nur eine Variante bei der Nicht-Strikten Auswertung ist. --Prometeus 18:50, 8. Apr 2005 (CEST)
- Sehe ich bisher nicht so. Was sollen denn andere Variante einer nicht-strikten Auswertung sein außer der Bedarfsauswertung? Steht das in eurem Skript? Kann man sich das anschauen? --fschoenm 01:39, 9. Apr 2005 (CEST)
- Also im Prinzip ist das, was du Lazy-Evaluation nennst unsere Definition der Nicht-Strikten Auswertung und was wir Lazy-Evaluation nennen ist das Konzept, dass doppelt vorkommende Teilausdrücke nicht doppelt sondern nur einmal ausgewertet werden. Z.b. führt so etwas wie
square x = x * x
- zu folgender Auswertung
square (3 + 5) = (3 + 5) * (3 + 5) = 8 * 8 = 64
- Ohne LazyEvaluation ergäbe das
square (3 + 5) = (3 + 5) * (3 + 5) = 8 * (3 + 5) = 8 * 8 = 64
- Nachlesen könntest du das z.B. auf http://programmierung.informatik.rwth-aachen.de
- Wahrscheinlich haben wir beide Recht und es ist einfach eine weit verbreitete begriffliche Ungenaugikeit ;-) --Prometeus 21:19, 9. Apr 2005 (CEST)
- Hab auf deiner angegebenen Website keinen Hinweis gefunden, aber auch nicht so lange gesucht. Aber Non-strict functional languages have another powerful feature: they only evaluate as much of the program as is required to get the answer - this is called lazy evaluation [1] klingt für mich eher nach der mir bekannten Definition. Ich habe auch das Gefühl, dass ich das von dir im Beispiel gezeigte Konzept auch schon mal in irgendeiner Vorlesung gesehen habe – allerdings nicht unter dem Schlagwort lazy evaluation. --fschoenm 21:32, 9. Apr 2005 (CEST)
- Hm, wenn das von offizieller Seite kommt würd ich nat. auch die Definition nehmen, die für dich spricht, klar. Uns wurde es halt so erklärt. Auf der Seite müsstest du unter Literatur das Skript vom Giesl finden, da ist das mehr oder weniger so erklärt, aber wie gesagt: Offizielle Seite geht natürlich vor. --Prometeus 21:54, 9. Apr 2005 (CEST)
- Na ja, »offiziell« ist haskell.org für Haskell, aber nicht allgemein für funktionale Programmierung. Meines Wissens besteht bezüglich des Begriffs »lazy evaluation« kein rechter Konsens unter Wissenschaftlern. Die einen bezeichnen damit ganz allgemein alle Konzepte, die Argumente nicht streng auswerten, andere nur solche, die Mehrfachauswertung vermeiden. Es gibt allerdings noch einen Begriff, der klarer definiert ist, und zwar »normal order evaluation«. Dieser bezeichnet ganz explizit das Konzept, Argumente nicht streng, aber bei jeder Verwendung erneut auszuwerten. Verwirrend ist das alles schon... Vielleicht sollte man die Begriffsungenauigkeit im Text explizit erwähnen. --Mulk 16:27, 24. Jul 2006 (CEST)
Es gibt drei gebräuchliche Auswertungsstrategien, und da ist sich die Literatur auch meines Wissens nach einig:
- call by value <-- das übliche, wie in Java, usw., d.h. strict.
- call by name <--
- Der Ausruck, der an die Variable gebunden wird, wird an jede Stelle, an der Variable gebraucht wird, kopiert. Dieser Ansatz wird aber soweit mir bekannt in keiner Programmiersprache verwendet.
- call by need <-- lazy, z.B. Haskell --Phillip 16:27, 28. Mai 2008 (CEST)
Überarbeiten
Bearbeitenbitte zumindestens erstmal die einleitung verständlich machen.--Archiv 14:51, 15. Nov 2005 (CET)
- Volle Zustimmung! Ich möchte dringend nahelegen, die Änderungen vom 4. November rückgängig zu machen. Die neue Einleitung hat kaum mehr Informationen als die alte, ist aber viel unverständlicher und umständlicher geschrieben. Begriffe wie "zuvorderst" und "faßlicher" klingen, als stammte der Text aus einem Lehrbuch der 70er Jahre. -- --Einmaliger 09:45, 18. Nov 2005 (CET)
hab die einleitung ausm englischen übernommen. lass überarbeiten drin, da der rest bisschen flüssiger gestaltet werden könnte. --Archiv 18:19, 19. Nov 2005 (CET)
Überarbeitung
BearbeitenOK, mein erster Wikipedia-Hilfsversuch... ist die Einleitung jetzt besser (ich fand die alte Fassung gar nicht so graesslich, ehrlich gesagt...)? Der Artikel ist immer noch sehr unvollstaendig; waere es stilistisch akzeptabel, mehr Beispiele zu verwenden und diese nicht in einen separaten Absatz einzusperren, oder wuerde das eher in eines der anderen Wiki-Projekte gehoeren?
--Creichen 05:51, 23. Nov 2005 (CET)
- ich hatte die einleitung bereits bearbeitet... aber nach wie vor sollte sie noch mal geändert werden, da begriffe wie Interpretation, Kompilierung, Normalform, λ-Kalkül, operationale und denotationale Semantik, referentiellen Transparenz den lesefluss stören für leute die sich nur informieren wollen. ich denke in der einleitung sollten keine fachtermini auftauchen und wenn - allgemeinverständlich erklärt werden. ein knappes aussagekräftiges beispiel in den absätzen mit erklärung ist aber immer gut. viel spass in der wikipedia. --Archiv 12:10, 23. Nov 2005 (CET)
Lazy evaluation
BearbeitenDas Problem mit dem obigen Beispiel aus der Lazy Evaluation ist im Kern der Unterschied zwischen "call by need" (mit sharing) und "call by name" (ohne sharing). Im imperativen Bereich ist die Unterscheidung wichtig (wg. Seiteneffekten) aber im Funktionalen nimmt man i.A. einfach "call by need" (cf. Peyton Jones, Impl. of Functional Programming Languages, 1987). Grund dafuer ist, dass es sich im Wesentlichen um Graphenreduktion handelt (ist nett in einigen der Clean-Papers erklaert, aber i.A. spricht alle Literatur, die "lambda graphs" erwaehnt, davon).
Macht es Sinn, diese Info in den Artikel nachzuruesten?
--Creichen 06:10, 23. Nov 2005 (CET)
Hauptproblem des Artikels
BearbeitenDer Artikel enthält so viele Fach und Fremdwörter, dass man ein halbes Informatikstudium benötigt um ihn zu verstehen, zumindest muss man soviel wissen, dass man schon weiß was Funktionale Programmierung ist. Ich bin zwar eigentlich Skeptisch, wenn „Oma-Kompatibilität” von Artikeln gefordert wird, aber ich finde es schlecht dass der Artikel nicht mal „Programmierer”-Kompatibilität hat. Ich denke unser Ziel muss sein den Artikel wieder auf ein verständliches Niveau zu bringen. Deshalb hab ich mal die Abgrenzung zur imperativen Programmierung hinzugefügt. Ich bin zwar noch nicht ganz zufrieden mit dem Stück, aber ich glaube solch ein Beispiel macht einiges verständlicher.--Rbb 17:41, 14. Feb 2006 (CET)
Ist die Einleitung jetzt besser? hab die Fachtermini entfernt ? --Tobini 23:32, 16. Mär 2006 (CET)
Überarbeiten
BearbeitenIch finde den Artikel zu fundamentalistisch. Er geht sehr detailliert auf die Vorstellung von Haskell und Lisp ein, lässt aber Smalltalk außen vor. Aus Smalltalksicht bedeutet funktionale Programmierung: Funktionen dürfen als Parameter übergeben werden und Schleifen werden (syntaktisch) durch fast gleichlautende funktionale Ausdrücke ersetzt.
- Der Artikel lässt auch Python, PHP, JavaScript und C++ aussen vor, obwohl man hier Sprachbestandteile finden kann, die aus der funktionalen Programmierung stammen und das ist genau richtig!
- Die Präsentation der Ideen eines Programmierparadigmas sollte an Hand einer Programmiersprache erfolgen,
- die speziell für dieses Paradigma designt wurde (möglichst ein reiner Vertreter und kein Vertreter multipler Paradigmen), weil das Paradigma klar erarbeitet werden soll und
- es sollte eine aktuelle, gängige Programmiersprache sein, wo noch ein wenig Leben bzw. gar Wachstum herrscht (aktuell) und viele Leute damit arbeiten (gängig)! Entweder wird noch dran geforscht oder die Sprache hat eine hohe Relevanz in der Industrie, so dass dort noch Neuentwicklungen stattfinden oder es gibt eine starke Open Source Gemeinde.
- Deshalb wäre Smalltalk bereits kein guter Kandidat für das OOP Paradigma, da es die erste Bedingung erfüllt, aber die zweite schon nicht mehr. Smalltalk für die Illustration funktionaler Programmierung verwenden zu wollen ist Trolling.
- --Smalltalk ist zwar nicht funktional, aber gewiss nicht tot. Bspw. hat kürzlich die Deutsche Bahn DaRT (Fahrzeugverwaltung) u.A. in VisualWorks entwickelt. (anonym 12:50, 2. Juli 2006 (CEST))
- --Marc van Woerkom 09:52, 13. Jun 2006 (CEST)
- --Blabla. Und anderes des Trollens zu bezichtigen ist Trollbezeichning. igel+- 10:57, 14. Jun 2006 (CEST)
- --S.o. Smalltalk hat Seiteneffekte und verletzt damit eine wichtige Eigenschaft funktionaler Sprachen, nämlich die Werttreue. (anonym 12:46, 2. Juli 2006 (CEST))
- Richtig. Smalltalk kann man imperativ programmieren oder funktionsal, genau wie Perl oder Ruby. Das ist eben nicht die volle Dosis funktional, wie sie Haskell bietet, aber auch funktional. Man MUSS ja keine Seiteneffekte auslösen. (mal von Zugriffen auf die Hardware abgesehen, aber das Problem hat Haskell ja irgendwie auch. Nomaden oder so) igel+- 09:26, 28. Jul 2006 (CEST)
Ein Beispiel. Eckige Klammern "[" und "]" begrenzen Funktionsblöcke. Solche sind wieder Objekte und haben Methoden.
[n < 8 ] whileTrue: [Transcript put: "Yippie Nummer " + n. n := n+1]
Wobei hier auf einem Funktionsobjekt die Methode whileTrue ausgeführt wird. WhileTrue ist so oder so ähnlich definiert:
whileTrue: aFunction ^ (self evaluate) ifTrue: [self whileTrue: aFunction]
Das "^" ist eigentlich ein Pfeil nach oben und bedeutet "return". Verständlicher wäre vllt ifTrue, das das in anderen Programmiersprachen übliche if ersetzt. If ist eine Objektmethode von True und False und sieht so (oder ähnlich) aus:
In der Klasse True:
ifTrue: aFunction ^ aFunction evaluate
Und in der Klasse False:
ifTrue: "Hier passiert nichts.
--Richardigel 23:45, 25. Mär 2006 (CET)
Hinweis auf Objektorientierte Weiterentwicklungen und "praktische" Parallität
BearbeitenInzwischen habe ich einige Artikel über Objektorientierte Weiterentwicklungen gelesen. Wäre nicht schlecht, wenn dies auch erwähnt würde.
Zusätzlich fehlt mir persönlich noch ein Hinweis auf den - praktischen - Unterschied von funktionalen Programmiersprachen. z.B. leichter für parallele Ausführungen optimierbar sind, oder der Programmierer damit einen höheren Grad an Parallelität verwalten kann, als in in Prozuduralen/Objektorienten möglich wäre.
(Vorstehender nicht signierter Beitrag stammt von 84.144.236.24 (Diskussion • Beiträge) 00:40, 27. Jun 2006)
- OO-Weiterentwicklungen werden im FPL-Bereich meist als eher überflüssig angesehen. Die besonderen Vorzüge von OO (Kapselung, polymorphe Container) werden durch andere Sprachmittel erreicht (Modularisierung, Closures statt Daten in den Containern).
- Es gibt einige FPLs, für die OO-Erweiterungen existieren, aber das Echo zumindest in comp.lang.functional ist zumeist: "Gibt es, hab ich bisher noch nicht gebraucht."
- D.h. wenn, dann ist das Thema nur einen Nebensatz wert.
Überarbeiten, die vierte
BearbeitenVielleicht könnte man den Artikel damit beginnen, den Unterschied zwischen Ausdruck und Anweisung herauszuarbeiten und dann funktionale Programmierung definieren als Programmierung von Programmen, deren Ablauf wesentlich (oder bei rein funktionalen Programmiersprache ausschließlich) aus dem Auswerten von Ausdrücken besteht. Die comp.lang.functional-FAQ schreibt beispielsweise
- Functional programming is a style of programming that emphasizes the evaluation of expressions, rather than execution of commands. The expressions in these language are formed by using functions to combine basic values. A functional language is a language that supports and encourages programming in a functional style.
Ich denke, mit dieser Definition wäre der Kerngedanke der funktionalen Programmierung erstmal klar umrissen. Davon ausgehend könnte man dann die strikteren Definitionen von John Backus (aus seiner „Turing Award“-Vorlesung von 1977: Can Programming Be Liberated From the von Neumann Style?) und John Hughes (Why Functional Programming Matters) anführen und aufzeigen, warum referenzielle Transparenz erstrebenswert ist, statt sie von vorneherein als definierendes Merkmal der funktionalen Programmierung aufzuführen.
Beim Lesen der obigen Diskussionen ist bei mir die Frage entstanden, ob möglicherweise im deutschen Sprachraum der Begriff der funktionalen Programmierung enger gefasst ist als im englischen Sprachraum. Kann jemand dazu etwas sagen? Ich bin mit der deutschen Literatur nicht so vertraut. — Tobias Bergemann 10:01, 28. Jul 2006 (CEST)
- Ich kann dir zwar deine Frage nicht beantworten, aber die obige Ausführung finde ich hemmungslos richtig. Genau so wünsche ich mir den Artikel. igel+- 10:07, 28. Jul 2006 (CEST)
- Offensichtlich haben viele Leute unterschiedliche Ansichten über den gwünschten Aufbau des Artikels und anscheinend auch über die richtige Definition des Lemmas selbst. In solchen Fällen hat sich bei anderen Artikeln ein zunächst strikt quellenbasierter Aufbau des Artikels bewährt, d.h. man sagt nicht „Funktionale Programmierung ist dies und das“ sondern eher „Der Informatikpionier Xaver Ypsilanti definiert funktionale Programmierung in seinem weitverbreiteten Lehrbuch/vielbeachteten Artikel so und so“. Auf diese Weise wird oft den sonst sehr kontroversen Diskussionen die Luft aus den Segeln genommen und man kommt rasch zu einer konstruktiven Zusammenarbeit zurück.
- Vielleicht sollten wir also erstmal damit beginnen, uns über die relevanten Quellen zu einigen?
- — Tobias Bergemann 10:15, 28. Jul 2006 (CEST)
- Auch das ist schwierig. Die einen werden auf Lisp-Literatur bestehen, die anderen auf hochtheoretischen Texten, die dritten auf Simon Peyton-Jones.
- Meine persönliche Definition ist die Nutzung von HOFs plus die Möglichkeit, Funktionen erst zur Laufzeit zu erstellen.
- C und C++ sind damit außen vor (HOFs sind drin, aber sie können Funktionen nicht zur Laufzeit erzeugen), Smalltalk ist (unerwartet, aber nicht unberechtigt) drin, Lisp auch.
- Danach den Schlenker über referentielle Transparenz (wichtig, da es bei HOFs oft schwierig ist, dem Code anzusehen, wann genau ein Ausdruck ausgewertet wird, und ohne RT führt das zu subtilen, schwer diagnostizierbaren Fehlern). Damit werden dann auch die Gründe einsichtig, warum RT für viele FPLs eine so große Rolle spielt, ohne dass man deshalb referentiell intransparente Sprachen wie Lisp oder Smalltalk gleich als nichtfunktional klassifizieren müsste (im Fall von Lisp würde das auch auf entrüsteten Widerspruch stoßen).
- Gerade die Betonung einer persönlichen Definition von funktionaler Programmierung muss der Artikel aber vermeiden, wenn wir den Gefahren der Theoriefindung und der Verletzung des Neutralitätsprinzips entgehen wollen. Wenn es keine allgemein anerkannte Definition von funktionaler Programmierung gibt, dann muss der Artikel das auch sagen und die verschiedenen Definitionen mit ihren Quellen anführen und vergleichen. Das ist sicherlich nicht einfach und wäre wohl eher eine Aufgabe für einen in der Quellenarbeit geübten Historiker als für einen Informatiker/Softwareware-Entwickler. Darum meine Frage: Welche Literatur sollte der Artikel überhaupt zu Rate ziehen und zitieren? — Tobias Bergemann 13:03, 8. Jun. 2007 (CEST)
- Um sich über die Literatur klar zu werden, und über die Autorität zu diskutieren, die hier heran gezogen werden kann, würde gern folgendes Vorgehen vorschlagen: Es gibt die Konferenz ICFP (International Conference of Functional Programming), die als Autorität in diesem Gebiet herangezogen werden kann. Eine Reihe, wenn nicht alle bekannten Persönlichkeiten der Funktionalen Programmierung (u.a. Simon Peten Jones, John Huges, usw.) publizieren hier regelmäßig Paper, sind im Programmkomitee vertreten und/oder halten dort Vorträge. Ein Besuch auf der Seite der ICFP zeigt, dass es u.a folgende Workshops gibt: Haskell, Scheme, Erlang
- Daraus finde ich läßt sich sehr gut ablesen, dass Scheme eine funktionale Programmiersprache ist, sonst würden die entsprechenden Wissenschaftler doch diese Workschop nicht zusammen mit der ICFP abhalten. Da Scheme Seiteneffekte unterstützt, werden sich vermutlich die meisten Wissenschaftler auf folgende Definition einlassen:
- Funktionen müssen first class values sein, d.h. die Closers müssen als Parameter an anderen Funktionen übergeben werden können
- Seiteneffekte sind möglich, allerdings dann ist die Sprache nicht mehr eine reine funktionale Sprache. Außerdem sind Seiteeffekte unerwünscht
- Legt man den ersten Punkt als Grundlage, kann man das Paradigma ganz gut anhand eines map, fold, oder filter Beispiels aufziehen. Ein gute Begründung, wieso man den zweiten Punkt gern hätte, kann dann eine einfache Programmtransformation liefern, die fehlerhaft ist, falls der Code Seiteneffekte ausführt --Phillip 16:28, 28. Mai 2008 (CEST)
Nach etwas Grübeln und Suchen nehme ich an, HOFs sollen „Funktionen höherer Ordnung“ sein, ja? Und ich entnehme der Diskussion, daß die Unterstützung dieser HOFs nach übereinstimmender Auffassung ein notwendiges Kriterium für das Attribut „funktional“ ist.
Könnten wir die Debatte, ob nur rein funktionale Sprachen als solche bezeichnet werden, vielleicht durch eine Aufstellung entschärfen, etwa so:
Sprache | HOFs | zur Laufzeit erzeugbar |
Seiteneffekte | imperativ |
---|---|---|---|---|
Rein funktionale Sprachen | ||||
Lisp | ja | ja | nein | |
Haskell | ja | ja | nein | |
Funktionale Sprachen | ||||
Python | ja | ja | möglich, z. B. wenn Variablen aus Modul importiert oder als global deklariert |
ja |
Smalltalk | ja | ja | ja | |
Scheme | möglich |
(Angaben für alle außer Python ohne Gewähr; Python hat aus Haskell außerdem seine Listenoperationen entlehnt)
Damit könnte dann jeder selbst beurteilen, welche Sprachen seine persönlichen Kriterien erfüllen; wobei unstrittig sein dürfte, daß eine Sprache mit imperativen Elementen keine rein funktionale sein kann. Die Puristen wären dadurch besänftigt, daß ihre Lieblinge ganz oben in der Liste stünden ;-)
Ich könnte mir eine solche Liste ggf. auch in einem separaten Artikel vorstellen. --Tobias 19:59, 12. Jun. 2009 (CEST)
Anwendungsbereich
BearbeitenMich würde interessieren, wo die funktionalen Grenzen der Funktionalen Programmierung liegen ;)
Ich möchte z.Bsp. einen Logger programmieren. Ein Datenlogger benötigt eine Funktion wie "WelcheZeitIst(Jetzt)". Dies kann im Sinne der FP keine Funktion sein (da sie bei stets selbem Input (jetzt) ein wechselndes Output hat - sie ist nicht "werttreu"). Wie kann man das Problem lösen? Durch Erzeugen von vielen Funktionen (eine für jede Sekunde oder Millisekunde der Uhr), die ihren Rückgabewert dann irgendwann mal abliefern? Oder geht das auch eleganter? Und kann jemand ein (deutchsprachiges?) Forum für solche Fragen empfehlen? :) --Modran 23:56, 6. Nov. 2006 (CET)
- Man kann eine Funktion schreiben, die als Eingabe die Uhrzeit entgegennimmt und als Ausgabe eine Liste durchzuführender Aktionen hat (in dem Fall Ausgabe einer Protokollzeile).
- Ein deutschsprachiges, recht einsteigerfreundliches Forum für solche Fragen ist news:de.comp.lang.functional .
- Echte Grenzen gibt es nicht. Im Extremfall kann man sogar die komplette imperative Programmierung nachbilden, einschließlich Seiteneffekte; die Unterschiede sind relativ fließend.
- Weil hier die Frage aufkam, wo die Grenzen der funk. Programmierung liegen, habe ich mal den Abschnitt zur Mächtigkeit in den Artikel eingefügt. Dies klärt hoffentlich, dass es vom Prinzip keine Grenzen gibt, die die imperative Programmierung nicht auch hätte. Die Frage ist also nicht, was ist die Grenze, sondern eher, wie aufwendig ist das Paradigma im dem ein oder anderen Fall. --Phillip 16:28, 28. Mai 2008 (CEST)
Beispiele
BearbeitenIch finde es könnten einfachere Beispiele verwendet werden. Wie die obig aufgeführten map und die Fakultät. Die hat man dann meist auch schon gelesen und verstanden.
Die Programmiersprachen SML und Joy mögen zwar nach der reinen Lehre funktional sein; eine große Verbreitung scheinen sie mir aber nicht zu haben. Deshalb habe ich ein Beispiel aus XSLT hinzugefügt, einer Sprache, die zur Transformation von XML nach XHTML im Internet weit verbreitet ist und die ich täglich bei der Arbeit an XML-Transformationen verwende. Jürgen Regel 17:11, 29. Mär. 2008 (CET)
Ungenauigkeiten
BearbeitenZ.B. Abgrenzung von imperativer Programmierung, Teil „funktionale Lösung“ (aber auch an anderen Stellen): man füttere die gezeigte Funktion mit irgend einer Zahl, die nicht Element der natürlichen Zahlen ist …
Dazu dann noch diese Darstellung im Pseudo-Code: „wenn … dann … sonst wenn …” – mit Basic geboren und nicht tot zu kriegen? Beim Beispiel, das schon angesprochen wird, fehlt also gleich jegliche Rückgabe. Selbst C hat da schon vor Jahren gelernt, wenigstens ein “warning” abzusetzen.
Stil
BearbeitenEine funktionale Programmiersprache ist eine Programmiersprache, die funktionale Programmierung unterstützt, indem sie Sprachelemente zur Kombination und Transformation von Funktionen anbietet. Hört sich an wie: Der Ball ist rund....-- Kölscher Pitter 15:19, 19. Jun. 2008 (CEST)
Hinweis
BearbeitenDer logische Ausdruck ist nicht falsch sondern wahr. Man sollte den entsprechenden Satz im Artikel dahingehend verändern, dass es nicht zu Missverständnissen kommt.
- Zugegeben etwas unglücklich formuliert. Wenn du aber schon eine neue gute Idee hast, ändere du es doch gleich. Fragen und Ähnliches immer unterschreiben =) Grüße --WissensDürster 12:04, 10. Jan. 2009 (CET)
Verständlichkeit der Beispiele
BearbeitenDie Verständlichkeit der Beispiele könnte vielleicht durch Hervorhebung der Schlüsselwörter verbessert werden (für die funktionalen Sprachen scheint es leider kaum entsprechende Unterstützung zu geben, im Unterschied zu XML, was sich für XSLT verwenden läßt). Ich vermute mal folgende Schlüsselwörter (die dann „händisch“ hervorgehoben werden könnten):
- Haskell
- Floating
- SML
- local, val, in, fun, end
- Joy
- DEFINE, dup, swap
Das Joy-Beispiel ist ohne derartige Unterstützung (und ohne Kenntnis der Sprache, natürlich) ziemlich unverständlich. Könnten sich die Kenner der jweiligen Sprachen mal äußern? Danke! --Tobias 19:13, 12. Jun. 2009 (CEST)
Sinn und Zweck
BearbeitenIch weiß nicht, ob ich der Einzige bin, der hier vergeblich die Antwort auf die Frage gesucht hat, was denn der Zweck des (rein) funktionalen Paradigmas ist; ich bin sicher, es gibt einen.
Aber die bisherigen Beispiele zeigen nur simple Funktionen, mit denen man keinen pascalprogrammierenden Hund hinterm Ofen hervorlockt; das ist schlicht strukturierte Programmierung (und auch Rekursion gibt es vermutlich in so gut wie jeder imperativen Programmiersprache). In Python könnte ich das Ringflächenbeispiel wie folgt schreiben:
def ringarea(r1, r2):
from math import pi
return pi * (r1**2 - r2**2)
... aber es wäre mir nicht im Traum eingefallen, das als Beispiel für Funktionale Programmierung in Python zu sehen. Auch mit dem Beispiel der Fakultät oder, als Negativbeispiel für besser nicht rekursiv zu lösende Probleme, der Fibonacci-Zahlen, überzeugt man niemanden. Kann denn niemand ein Beispiel einbringen, das auf überzeugend einfache Weise funktional zu lösen ist? Die Türme von Hanoi sind wohl ein Beispiel für Rekursion; gibt es eins, für das man Funktionsobjekte braucht? --Tobias 16:55, 22. Jun. 2009 (CEST)
Quadratwurzel in Python
BearbeitenIch habe mich mal daran gemacht, die Berechnung der Quadratwurzel nach Newton-Raphson (das Beispiel aus dem verlinkten Artikel von John Hughes, Seiten 9 bis 11) in Python umzusetzen, um zu sehen, inwieweit das funktionale Paradigma unterstützt wird. Natürlich wird man in Python üblicherweise, wenn es nur um diese konkrete Berechnung geht, alles in eine Funktion stecken, in der rekursiven Variante z. B. so:
def sqrt(N, x, eps):
nv = (x + N/x) / 2
# print '...', nv # (zur Ausgabe der Zwischenergebnisse)
if abs(nv-x) < eps:
return nv
return sqrt(N, nv, eps)
Es geht aber auch folgendes:
def next(N, x): # (1)
return (x + N/x) / 2
def repeat(f, first): # (2)
while True:
yield first
first = f(first)
def within(eps, seq): # (3)
x = None
for nv in seq:
# print '...', nv # (auskommentiert)
if x is None: # leider nötig (siehe unten)
pass
elif abs(nv-x) < eps:
return nv
x = nv
def sqrt(N, eps, first): # (4)
return within(eps,
repeat(lambda x: next(N, x), # (5)
first))
N = 2.0 # (6)
eps = 0.000001
startwert = 1.0
print 'sqrt(%f, %f, %f) -> %r' % (N, eps, startwert, sqrt(N, eps, startwert))
- Die Funktion next generiert die nächste Iteration an+1, basierend auf dem Eingabewert N und an
- Die Funktion repeat generiert eine Sequenz, indem sie einen Startwert first ausgibt und dann die übergebene Funktion f wiederholt auf diesen Startwert bzw. das Ergebnis der vorigen Iteration anwendet. Es wäre z. B. möglich, mit
repeat(lambda n: n+1, 1)
die natürlichen Zahlen zu generieren (bis die nächste Zahl durch den aufrufenden Code nicht mehr angefordert wird) - Die Funktion within liest die (z. B. mit Hilfe von repeat) generierte Sequenz und gibt das erste Element zurück, das sich von seinem Vorgänger um weniger als eps (Epsilon) unterscheidet
- Die Funktion sqrt setzt nun die bis hierher definierten Funktionen zusammen, um die Quadratwurzel zu berechnen:
- Es wird mit Hilfe von repeat eine Sequenz mit dem Startwert first generiert;
- die Funktion within filtert aus dieser Sequenz den gewünschten Näherungswert.
- Da für repeat eine Funktion mit nur einem Argument benötigt wird und N über alle Aufrufe gleich bleibt, wird eine Funktion erzeugt und übergeben, die diesen Wert N bereits kennt (Closure); „lambda x: next(N, x)“ entspricht Hughes' „(next N) x“
- Verwendung der Funktion zur Berechnung der Quadratwurzel von 2:
- Die 2 wird als Fließkommazahl angegeben, damit nicht irrtümlich ganzzahlig dividiert wird
- Das Ergebnis wird als %r formatiert, um Rundung zu vermeiden (z. B. für Experimente mit Epsilon)
Abgesehen davon, daß repeat und within nicht rekursiv definiert sind, sondern mit Hilfe von Generatoren, entspricht diese Python-Implementierung genau Hughes' Beispiel; so ist es hier gleichermaßen möglich, durch Verwendung einer anderen within-Funktion das Abbruchkriterium zu ändern.
Nun weiß ich nicht, ob Hughes' Miranda-Beispiele hier aufgeführt werden dürften; aber möglicherweise ist das hier ja schon hilfreich – zumindest ist es ganz gut lesbar, und es kann sicher bei der Entscheidung helfen, ob Python nun eine funktionale Programmiersprache ist... Vielleicht ist es ja funktional, aber nicht deklarativ? Sind rein funktionale Sprachen generell deklarativ? --Tobias 16:15, 23. Jun. 2009 (CEST)
Einschränkungen in Python
BearbeitenObige within-Funktion ließe sich natürlich auch in Python rekursiv definieren; allerdings klappt das leider nur für Sequenzen bekannter Länge:
>>> seq = list()
>>> for i, e in zip(range(9), repeat(lambda x: x/2, 1.0)):
... seq.append(e)
...
>>> seq
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625]
>>> def within(eps, seq):
... first = seq[0] # (Variablen nur zur
... second = seq[1] # besseren Verständlichkeit)
... if abs(second-first) < eps:
... return second
... return within(eps, seq[1:])
...
>>> within(0.01, seq) # oben erzeugte Sequenz bekannter Länge
0.0078125
>>> within(0.01, repeat(lambda x: x/2, 1.0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in within
TypeError: 'generator' object is unsubscriptable
>>>
Daher oben der Umweg über den Vergleich mit None. --Tobias 16:15, 23. Jun. 2009 (CEST)
Überarbeiten entfernt
BearbeitenIch habe die Überarbeiten-Vorlage entfernt. Diese war sehr lange am Artikel und ich glaube, dass die nicht mehr nötig ist. Sollte jemand anderer Meinung sein, dann bringt sie wieder an und begründet das. --Qbi 16:59, 29. Okt. 2009 (CET)
Funktionenbegriff Informatik bzw. Mathematik
Bearbeiten"Der Begriff der Funktion wird in Informatik und Mathematik mit unterschiedlicher Bedeutung verwendet" Das ist so sicherlich gerade nicht richtig. Der Link auf das Lemma der "Funktion (Programmierung)" macht dies garantiert nicht besser, sondern verleitet den Laien dazu, dass "Informatik" und "Programmieren" das Gleiche ist. Vielmehr besteht zwischen den wissenschaftlichen Fachrichtungen Informatik und Mathematik mit Sicherheit bei dieser Begrifflichkeit Einigkeit. Informatik und Programmieren ist nunmal nicht das Gleiche. (nicht signierter Beitrag von 84.59.12.159 (Diskussion | Beiträge) 01:46, 4. Jan. 2010 (CET))
Das ist leider etwas komplizierter. Grundsätzlich hat die Mathematik hier die Oberhoheit: Eine Funktion ist eine injektive Relation. So weit so gut. Nur gibt es in der Informatik einen weiteren, eher metaphorischen Begriff, bei dem es aber nicht um die Einordnung von Relationen geht, sondern um ein Konstruktionselement von Programmiersprachen. Die korrekte Bezeichnung ist übrigens Lambda-Abstraktion, und man müsste statt "funktionale Programmiersprache" eigentlich "Programmiersprache, bei der die Lambda-Abstraktion grundsätzliches Konstruktionselement ist" sagen. Macht natürlich niemand. Die Autoren des Artikels haben diesen Kategorienunterschied leider nicht verstanden, sonst würden sie explizit darauf hinweisen, und der ganze Artikel wäre viel verständlicher. Zwar ist es richtig, dass man mit Hilfe einer Lambda-Abstraktion eine Funktion in mathematischem Sinn definieren kann, aber darin erschöpft sich die Gemeinsamkeit schon. -- Gerd Stolpmann (nicht signierter Beitrag von 84.58.57.23 (Diskussion) 17:17, 22. Feb. 2012 (CET))
Scala: Überarbeiten-Baustein
BearbeitenDas gezeigt Programm berechnet nicht den Flächeninhalt eines Rings. -- Traxer 14:40, 17. Feb. 2010 (CET)
Was bitte hat das Scala "Hello World" Programm in dem Abschnitt über Flächeninhalte verloren??
92.72.166.197 04:52, 20. Feb. 2010 (CET)
Habe das Scala Beispiel überarbeitet und den Überarbeitungshinweis entfernt - sollte so stimmen. -- 92.194.94.44 21:53, 22. Feb. 2010 (CET)
Paradigmen der funktionalen Programmierung
BearbeitenSollte man die Paradigmen der funktionalen Programmierung nicht in einem eigenen Abschnitt aufführen. Ich wollte mir einen Überblick über die funktionale Programmierung verschaffen, fand dies aber schwierig, da die Paradigmen zwar mehrfach erwähnt, aber nirgens explizit genannt werden. Da ich nur geringe Erfahrungen auf dem Gebiet habe, traue ich mir diese Ergänzung momentan auf die Schnelle nicht zu -- KoniPaka 11:28, 15. Sep. 2010 (CEST)
Die Beispiele sind schlecht
BearbeitenIch bin doch etwas erstaunt ob der Trivialität des gegebenen Beispiels. Daran kann man nicht verstehen, was funktionale Programmierung bedeutet. Für Anfänger ist es am wichtigsten zu verstehen, dass Variablen nicht modifiziert werden können, und dass man mittels Rekursion oder Kombinatoren Zwischenwerte weiterberechnet, bis das Endergebnis erreicht ist, und dass es dabei von einer Variablen beliebig viele "Versionen" von Werten gibt. Eine Gegenüberstellung eines Faltungsoperators mit einer imperativen for-Schleife wäre hier zur Abgrenzung von der imperativen Programmierung hilfreicher.
Das Beispiel "Makefile" ist schlicht falsch. Makefiles modifizieren den Zustandsraum, der im Wesentlichen aus dem Dateisystem besteht. Makefiles sind nicht funktional, sondern eine deskriptive Form imperativer Algorithmen. -- Gerd Stolpmann (nicht signierter Beitrag von 84.58.57.23 (Diskussion) 15:54, 22. Feb. 2012 (CET))
Peinlicher Artikel
BearbeitenJetzt lese ich doch mal genauer. Ich glaube, die Autoren haben gar keine Ahnung, was FP eigentlich ist. Das fängt mit der Definition im ersten Abschnitt an: "Sprachelemente zur Kombination und Transformation von Funktionen" sollen charakteristisch sein. Das ist eine Wischiwaschi-Definition! Es ist doch kein Wunder, dass sich Leute beschweren, warum denn ihre Lieblingssprache nicht hier als funktional aufgeführt wird!
Eine bessere Definition: Eine FP ist eine Sprache, die (im Kern) den Lambda-Kalkül auf von-Neumann-Maschinen emuliert. Darum geht's nämlich: Wir haben einen mathematisch streng definierten Kalkül, aber Computer, die auf ganz andere Weise funktionieren. Eine (reale, zur praktischen Programmierung bestimmte) FP ist immer dadurch gekennzeichnet, dass sie diesen konzeptionellen Unterschied überbrückt, und dabei eine Reihe von Kompromissen eingeht. Warum gibt es denn nicht-pure FP-Sprachen? Weil nicht-pure Elemente auf einfache Weise auf Computern ausführbar sind, und man den Performance-Vorteil nutzen will. Um reale FP-Sprachen zu verstehen, muss man sich dieser Schwierigkeit bewusst sein.
Eine reine FP-Sprache ist übrigens eine Sprache, die keine Zuweisung von Variablen in irgendeiner Form kennt.
Zum Abschnitt "Funktionen in Mathematik und Programmierung": Das ist der größte Unsinn, den ich je gelesen habe. Zusammengereimt! Eine Funktion in der Mathematik hat nichts mit Algorithmik zu tun! Man kann ja Funktionen auf überabzählbaren Mengen definieren - wie wollt ihr das denn mit Lambda-Abstraktionen vergleichen? Das ist unterste Schublade.
Ich vermisse in dem Artikel wesentliche Definitionen, die für FP essentiell sind, etwa Variable, Closure (=Implementierung einer Lambda-Abstraktion mit Hilfe von gemerkten Environments), Rekursion, Abstraktion, Applikation.
Den ganzen Abschnitt über typisierte Sprachen sollte man eindampfen. Ein Verweis darauf, dass sich Typ-Kalküle angeben lassen sollte reichen. Das Thema ist nämlich endlos, und hat nur begrenzt mit FP zu tun. Typinferenz ist zwar vorherrschend bei FP, aber grundsätzlich nicht darauf beschränkt. SQL hat auch Typinferenz, und es gibt keinen Grund, warum man Typinferenz nicht für imperative Sprachen entwickelt können sollte. Interessant wäre hier eher noch, dass die Typisierung rekursiver Funktionen schwierig ist, und alle FP-Sprachen hier Kompromisse machen (z.B. Beschränkung auf regulär typisierte Rekursion).
Eine Funktion höherer Ordnung heißt übrigens Kombinator.
Der Stil des Artikels ist anfängerhaft: "Die theoretische Informatik hat gezeigt, ...". Das gehört sich nicht für Lexikon-Artikel. Schreibe das Faktum auf, und belege mit Quelle.
Ich glaube, der ganze Artikel krankt daran, dass er ein sehr abstraktes Konzept herunterbrechen will auf die Denkweise der einfachen Programmierer. Damit ist aber nichts gewonnen: Die Definitionen werden beliebig, und Abgrenzungen können nicht gezogen werden. Die einfachen Programmierer haben dann auch nichts davon. Ich würde es begrüßen, den Artikel umzuschreiben, und das Niveau hochzusetzen, so dass eine echte Charakterisierung möglich wird. Ein Lexikon-Artikel ist ja nicht als Einführung in ein Thema gedacht, sondern als Übersicht über das vorhandene Wissen.
Sorry für den Verriss. Wer sich ungerecht behandelt fühlt, beschwere sich bei mir (gerd@gerd-stolpmann.de). -- Gerd Stolpmann (nicht signierter Beitrag von 84.58.57.23 (Diskussion) 17:17, 22. Feb. 2012 (CET))
Funktionen in der Mathematik und der Programmierung
BearbeitenIch kann mich dem vorhergehenden Kommentator nur anschließen: Der Beitrag ist schlicht peinlich. Funktionen sind in der Mathematik Zuordnungen, die auf verschiedene Weise dargestellt werden können, zB. als Teilmengen eines cartesischen Produkts oder unter Rückgriff auf eine formale Sprache. Darstellung und Dargestelltes bringt der Autor komplett durcheinander. (nicht signierter Beitrag von Hebold (Diskussion | Beiträge) 07:26, 7. Mär. 2014 (CET))
Abschnitt "Mächtigkeit"
BearbeitenFolgender Absatz stößt mir sauer auf:
- "Die Mächtigkeit einer Programmiersprache ist definiert durch die Menge an Problemen, die in dieser Programmiersprache entscheidbar sind. Die theoretische Informatik hat gezeigt, dass eine reine funktionale Programmiersprache mit Rekursion gleich mächtig ist wie eine imperative Programmiersprache, die Schleifen und Zuweisungen erlaubt (siehe Turing-Vollständigkeit). Dies zeigt, dass das Einhalten des funktionalen Paradigmas keinerlei Einschränkungen mit sich bringt, auch wenn dies auf den ersten Blick so scheinen mag."
Mit dem Hinweis darauf, dass auch Brainfuck Turing-vollständig ist -- und mir mit Sicherheit niemand erzählen will, dass BF "keinerlei Einschränkungen mit sich bringt" -- stelle ich die obige Aussage in Frage und fordere Quellen, die genau das (Turing-vollstandig also folgt keine Einschränkungen) belegen. Da der Absatz ansonsten nicht viel zum Artikel beiträgt, und der folgende Absatz sehr viel weniger theoretisch Vor- und Nachteile aufzählt, würde ich den Absatz ansonsten löschen. -- 145.228.61.5 12:00, 2. Jun. 2015 (CEST)
Irreführende Beispiele
BearbeitenIch halte die Beispiele XSLT und Makefile für irreführend. Sie tragen nicht dazu bei FP zu erläutern. Beim Makefile habe ich Zweifel, ob die Behauptung stimmt, also ob diese den Lambda-Kalkül abbilden können. - Benutzer:West of House (21:21, 6. Jan. 2017 (CET), Datum/Uhrzeit nachträglich eingefügt, siehe Hilfe:Signatur)
Mehrere Abschnitte sind sehr schlecht
BearbeitenWer sich in der deutschsprachigen Wikipedia in das Thema funktionale Programmierung einlesen will, ist ziemlich angeschmiert. Das würde ich gerne ändern. Deswegen baue ich dieseswn und einen anderen Artikel seit ein ein paar Tagen vorsichtig um.
In diesem Hauptartikel ist der Abschnitt "Funktionen in Mathematik und Programmierung" völlig nebensächlich und erzeugt nur Verwirrung. Warum bekommen wir bewiesen, dass x=x+1 nicht gilt??
Dass irgendjemand behauptet, Funktionen seien ein adäquater Ersatz für Module habe ich so noch nicht gehört. Richtig ist eher, dass ein Satz von Closures über demselben Kontext als Modul-Ersatz fungieren kann. Ich finde der Abschnitt kann entfallen.
Der Absatz "Mächtigkeit funktionaler Sprachen" ist ziemliches Geschwurbel und am Ende auch falsch. Es gibt keinen nennenswertes Performancedefizit bei FP.
Ähnliche Probleme habe ich mit der Betrachtung über "rein funktionale Programmiersprachen". Die Betrachtung als solche ist absolut sekundär.
Bei dem Beitrag über "funktionen höherer Ordnung" habe ich den Eindruck, das der Autor eigentlich fachfremd ist. Einen formalen Unterschied zwischen Funktionen höherer Ordnung und erster Ordnung macht man in der Praxis garnicht, sondern verwendet einfach Funktionen ohne explizit darauf hinzuweisen, ob diese mit Funktionen frisst oder scheisst. Auch trifft keine mir bekannte funktionale Programmiersprache eine solche Unterscheidung.
Mein Vorschlag wäre, die erwähnten Abschnitte zu entfernen.
West of House (Diskussion) 22:22, 8. Jan. 2017 (CET)
- Es gibt tatsächlich einiges was man am Artikel verbessern könnte, ich frage mich zum Beispiel auch, ob es die vielen Syntax-Beispiele wirklich braucht.
- Ich finde "Funktionen in Mathematik und Programmierung" könnte entfernt werden, genau so wie "Mächtigkeit funktionaler Sprachen". Interessanter wäre vielleicht ein Abschnitt der skizziert, welche Ansätze funktionale Programmiersprachen verwenden, um Programme effizient zu machen?
- Bei "Funktionen höherer Ordnung" stimme ich deiner Kritik zwar zu, ich denke aber dass dieser Begriff zumindest irgendwo erwähnt sein sollte, da er doch in der Literatur immer wieder auftaucht. Wahrscheinlich braucht man aber nicht unbedingt einen eigenen Abschnitt hierzu. --Evotopid (Diskussion) 21:20, 11. Jan. 2017 (CET)
- @West of House: Danke für deine Artikelarbeit. Leider denke ich, dass deine letzte Änderung nicht in die richtige Richtung geht. Siehe WP:WWNI#9. Der Artikel sollte die funktionale Programmierung auf das wesentliche zusammenfassen und nicht beliebig ausführlich sein. Leider gibt es noch kein Wikibook "Funktionale Programmierung", welches sich mit den allgemeinen Aspekten auseinandersetzt, es gibt aber sehr wohl ein Buch b:Funktionale Programmierung mit Haskell. Ich denke vieles in diesem Artikel gehört eher in ein Wikibook als auf die Wikipedia. --Evotopid (Diskussion) 12:03, 12. Jan. 2017 (CET)
- @Evotopid: Ich glaube ich verstehe ungefähr, was Du meinst. Allerdings gibt es da das Problem, das der Artikel in der aktuellen Form das (ungeheuer wichtige) Thema FP nicht verwertbar erklärt. Sind es die Programmierbeispiele, die Dich stören? Man kann auch allgemeiner (mathematisch) weitermachen. West of House (Diskussion) 20:16, 13. Jan. 2017 (CET)
Abschnitte entfernt
BearbeitenIch habe die fraglichen Abschnitte "Funk in mathematik und infor." sowie "Mächtigkeit..." entfernt sowie einen Absatz der eine weiter oben schon erklärtes Konzept wiederholt hat.
Ich werde jetzt den mathematischen Teil seiner Programmiersprachenunabhängikeit wegen nach und nach ergänzen.
Mir ist aufgefallen, dass die Programmierbeispiele alle ein Beispiel behandeln, das nicht im engeren Sinne funktional ist und darum eher ungeeignet ist, das wesen von FP klar zu machen. Das ist schade, da viele Leute daran mitgewirkt haben. Ein besseres Beispiel wäre etwas mit map oder reduce oder noch besser ein ganzer Hylomorphismus. Und dann ein paar P-Sprachen weniger. Man muss nicht von jeder Codierform nachweisen, dass sie auch irgendwie ein bisschen funktional ist (Hat auch oben schon ein anderer Autor angemahnt).
Listen-Anamorphismus falsch.
BearbeitenSo ist's richtig (und sollte man nicht unbedingt sofort mit in einen Topf werfen) und die Dualität schön sichtbar:
, der Typ der endlichen Listen über zusammen mit ist initiale Algebra des Funktors . Das heißt, für alle und alle gibt es ein eindeutig bestimmtes , sodass folgendes Diagramm kommutiert.
, der Typ der möglicherweise unendlichen Listen über zusammen mit ist terminale Koalgebra des Funktors . Das heißt, für alle und alle gibt es ein eindeutig bestimmtes , sodass folgendes Diagramm kommutiert.
Bekanntlich muss es möglich sein, die Identität auf als Anamorphismus darzustellen. Mit meiner Formulierung geht's, mit der im Artikel nicht. Wenn wir uns in einer totalen Sprache befinden und der leere Typ ist, ist isomorph zu , und isomorph zu . Eine Funktion , also anzugeben, ist dann möglich (und trivial). Ein Paar von Funktionen , , also anzugeben, ist dagegen nicht möglich. --Daniel5Ko (Diskussion) 18:22, 19. Jan. 2017 (CET)
Jetzt bin ich aber platt, denn es ist mir nicht gelungen, kommutative Diagramme in die Wikipedia zu bringen und ohne das Modul tikcd(gibt es nicht) oder den Umweg über gifs(unschön). Sonst hätten wir längstens Artikel über Kata-, Ana-, Hylomorpihsmen und Para- wie Apomorphismen (da gibt es eine ganze Arbeit aus Estland 1990 drüber) ebenfalls.
Ich sehe aber keinen Fehler in der Definition Anamorphismus. Noch weniger, wo ich A* mit A8 verwechselt habe. Da müsstest Du mir helfen oder ihn direkt korrigieren. Danke.
West of House (Diskussion) 21:01, 19. Jan. 2017 (CET)
- Wie gesagt, der Fehler ist sichbar, wenn man versucht, die Identität auf als Anamorphismus anzugeben. Es gibt keine Funktion .
- Warum man zwischen und (ich betone zur Sicherheit: mit letzterem ist nicht der Typ der unendlichen Listen über A gemeint, sondern der der potentiell unendlichen Listen. dagegen enthält nur endliche Listen) unterscheiden sollte, wird klar, wenn man sich mit totalen Programmiersprachen beschäftigt. Siehe etwa Turner: Total functional programming als Einstieg. --Daniel5Ko (Diskussion) 22:22, 19. Jan. 2017 (CET)
Danke für die Information. Schlägst Du also vor, a* durch a8 zu ersetzen? Muss ich nicht iregendein epsilon einführen, um einfach mit a8 arbeiten zu können? Es ist ja nicht jede Liste unendlich lang, sondern eben nur potenziell. West of House (Diskussion) 17:05, 22. Jan. 2017 (CET)
- Wie man den Typ nennt der potentiell unendlichen Listen nennt, ist ja erstmal egal. Wichtiger ist aber zunächst, die Eingabedaten für den Anamorphismus zu ändern, sodass nicht eine Funktion und eine Funktion verlangt wird, sondern eben eine Funktion . --Daniel5Ko (Diskussion) 20:44, 22. Jan. 2017 (CET)
Well then. Es handelt sich also nicht wirklich um eine fehlerhafte Defintion und es geht dir auch nicht darum, ob a* oder a8, sondern um die Frage, ob ich zwei Funktionen p,g oder eine Funktion <p,g> verwende. Das können wir natürlich gerne ändern. Für das Thema Funktionale Programmierung stellt das aber je nach Programmiersprache eine echte Hürde dar, da nicht alle PS mit Mehrfachwerten umgehen können.
West of House (Diskussion) 08:40, 24. Jan. 2017 (CET)
- Nein. Nochmal: man kann eben nicht jede Funktion als Paar von Funktionen (was äquivalent zu einer einzigen Funktion wäre) darstellen. Beispiel: Nimm leer und bewohnt (und wir wollen nicht darauf angewiesen sein, partielle Funktionen benutzen zu können). Nur wenn wir auch partielle Funktionen haben können, geht das; aber es ist ja nicht die Essenz funktionaler Programmiersprachen, partielle Funktionen zulassen zu müssen. Für die Identität auf dem Typ der potentiell unendlichen Listen über dem leeren Typ als Anamorphismus braucht man die Formulierung mit .
- Was du mit "Mehrfachwerten" meinst, weiß ich nicht. ist jedenfalls ein Summentyp. --Daniel5Ko (Diskussion) 10:13, 24. Jan. 2017 (CET)
Ein Mehrfachwert ist ein Funktionsergebnis, das aus mehreren Einzelwerten besteht, also exemplarisch den Typ hat, wenn und Datentypen sind. West of House (Diskussion) 13:13, 26. Jan. 2017 (CET)
- Die Rückgabe von Records ist in jeder Programmiersprache, die die Bezeichnung verdient, prinzipiell möglich -- und sei es, indem man so etwas wie einen Satz von Zeigern übergibt, hinter die dann die Werte geschrieben werden sollen. Implementierungsdetails sollten hier aber keine Rolle spielen. --Daniel5Ko (Diskussion) 16:02, 26. Jan. 2017 (CET)
- Ich bin übrigens davor zurückgeschreckt, selber umfängliche Änderungen vorzunehmen, weil es für mein gefühltes Zeit- und Konzentrationsbudget zu große Kreise gezogen hätte. Du, West of House, schienst dagegen recht mitteilungsbedürftig (aufgrund der vielen Edits). Warum wird die Problematik nicht geeignet angegangen? Es würde ja reichen, das Problem zu benennen und explizit zu ignorieren. Man kann aber sicher auch 'was sinnvolleres basteln. --Daniel5Ko (Diskussion) 03:06, 11. Mär. 2017 (CET)
nicht zu verstehen
BearbeitenIch wollte mal schnell nachschauen, was "Funktionale Programmierung" ist. Habe aber null verstanden. Wer das verstehen kann, der weiss sowieso schon, was funktionale Programmierung ist.... --2.246.98.178 12:21, 11. Mai 2017 (CEST)
Danke für die Kritk
BearbeitenIn der Hoffnung das zu verbessern, habe ich die Einleitung abgeändert.
C++ Beispiel
BearbeitenIch habe mir die Beispiele angeschaut. Sollte da nicht noch C++ mit hin?
auto pi = 3.14;
auto squared = [](auto x) { return x * x; };
auto ringarea = [squared](auto r1, auto r2) { return pi * (squared(r1) - squared(r2)); };
C geht nicht funktional - irgendwas stimmt da nicht...
BearbeitenDie Definition bzw. Beispiele im Artikel passen mit "Populäre Sprachen, die keinerlei Möglichkeiten zur funktionalen Programmierung bieten, sind zum Beispiel C" überhaupt nicht zusammen. Ein C-Programm besteht ja schon primär aus der main()-Funktion, welche eigentlich standardkonform eine beliebige Liste an Parametern entgegen nimmt, und einen int-Wert bei Beendigung zurückgibt. Und Rekursion ist sowieso für eine mächtige Programmiersprache unerlässlich.
Überhaupt sollte man überdenken, ob die Grenzen zwischen den Programmierparadigmen so fundamental dargestellt werden sollten. Ein "stdout.print("Hallo Welt");" ist z.B. schließlich genauso imperativ wie "printf("Hallo Welt");", es wird nur objektorientiert verpackt. Grundsätzlich kann man so ziemlich alle Programmierparadigmen mit C verfolgen, es ist nur umständlich und der Compiler erzwingt natürlich keinen "guten Stil".--Mr. B.B.C. (Diskussion) 12:46, 18. Jun. 2020 (CEST)
- Nein, das ist nicht so. In funktionalen Programmiersprachen agieren Funktionen als "first class citizens" und können nicht nur in Variablen gespeichert werden, sondern auch zur Laufzeit algebraisch verknüpft werden (Das untersucht unter anderem die Kategorientheorie). Das kann C definitiv nicht. Da C auch keine lokalen Funktionen kennt, noch weniger eine lexikalische Bindungen abschließen (Closure bilden) kann, ist C alles andere als funktional. --West of House (Diskussion) 11:32, 14. Dez. 2022 (CET)
Weiteres Beispiel rein funktionaler Programmiersprache: Idris
BearbeitenIch kenne sie nicht, aber Idris
https://en.wikipedia.org/wiki/Idris_(programming_language)
(gibt es in der dt. Wikipedia noch nicht) scheint eine rein funktionale Programmiersprache zu sein. Sie wurde einem Bekannten jüngst empfohlen, so komme ich drauf. Da ich nicht weiß, wie ich "gut" Links ins Englischsprache mache, packe ich es hier hin, statt in den Artikel selbst -- 87.78.73.45 08:59, 21. Jan. 2021 (CET)
Den Abschnitt "Beispiele" würde ich gerne überarbeiten
BearbeitenDer Grund ist, dass das gewählte Beispiel "Kreisflächenberechnung" zwar mit lokal gebundenen Funktionen arbeitet, aber nicht charakteristisch für die Funktionale Programmierung ist. Eventuell kommt das Beispiel ja von einem Autor, der noch nicht praktisch in einem funktionalen Projekt gearbeitet hat.
Ich werde mir ein schlüssiges Alternatives Beispiel überlegen, dass auch die Vorteile erkennen lässt.
Für all' dies benötige ich aber Kenner verschiedener Programmiersprachen.
17:22, 22. Jul. 2021 (CEST) West of House (Diskussion)
- Da die ganze Geschichte höhere IT-Philosophie ist, die viele normale Programmierer überfordert (ich schmeiße seit über 30 Jahren täglich mit Lambdas um mich), ist es nicht verwunderlich, wenn es einem Beispiel nicht gelingt, das anschaulich zu erklären.
- Insofern können eine oder mehrere Alternativen durchaus helfen.
- Leider finden diese Beispiele immer nur diejenigen einfach, die sie sich selbst ausgetüftelt haben.
- Insofern empfehle ich, zunächst einen oder mehrere Vorschläge hier darzustellen; anschließend ließe sich überlegen, welche zukünftig den Artikel illustrieren sollen.
- Kenner „normaler“ Programmiersprachen werden von dem Konzept oft geplättet. Aber SQL würde helfen. Die wirklichen Vorteile stellen sich erst bei komplexen Aufgaben heraus, was kollidiert mit dem Begehren nach einer einfachen und anschaulichen Musterlösung.
- VG --PerfektesChaos 18:24, 22. Jul. 2021 (CEST)
Nur Vorteile ?
BearbeitenDie Kurzbeschreibung am Anfang erscheint nicht dem gebotenen neutralen Standpunkt zu entsprechen, denn außer der formalen Beschreibung werden explizit Vorteile herausgehoben, aber keine Nachteile genannt. Demnach würde die überwiegende Masse der Informatiker vorsätzlich mit dem falschen Werkzeug arbeiten. Vermutlich gibt es aber eben doch auch Nachteile und sei es nur ggf. eine schwerere Anwendung oder Rückwärtskompatibilität oder Performance. Aus meiner Sicht sollten diese ebenfalls kurz aufgeführt werden, wenn man Vorteile listet. Persönlich habe ich keine Präferenz für oder gegen diese Technologie, aber ich bin mir nicht so sicher, daß dies beim Verfasser (m,w,d,...) ebenfalls so ist. JB. --92.195.43.63 04:24, 8. Apr. 2022 (CEST)
- Die Kritik kann ich so nicht nachvollziehen. Wo werden da Vorteile herausgehoben? Die Einleitung spricht über Eigenschaften und nimmt keine direkte Bewertung vor. --West of House (Diskussion) 12:24, 8. Apr. 2022 (CEST)
- @JB:
- Naja, das ist schon etwas komplizierter.
- Es gibt zwei Problemfelder, die sich aber nicht als Nachteile der Sprache selbst einleitend festmachen lassen:
- Die Philosophie ist anders.
- Im Schulunterricht wird erstmal Imperative oder Prozedurale Programmierung mit Programmablaufplan erlernt.
- Von diesem ersten Ansatz bleibt nichts übrig, und es muss komplett umgedacht werden.
- Das schaffen nicht alle.
- Deshalb ist es nur ein sehr kleiner Kreis, der das umseitig beherrscht und anwenden kann.
- Wenn du nur einen Hammer hast, sehen alle Probleme wie Nägel aus.
- Umseitig eignet sich nur für eine kleinere Teilmenge von Problemen.
- Auf ungeeignete Aufgaben angewendet gibt es eine Bruchlandung.
- Da kann die Methode nix zu.
- Breiter wiederverwendbare, insbesondere Objektorientierte Programmierung, sind konzeptionell vertrauter und würden bevorzugt, selbst wenn theoretisch nicht so elegant.
- Die volle Wirkmacht kann sich erst entfalten, wenn alle Beteiligten und Maintainer das Prinzip verinnerlicht haben.
- Die Philosophie ist anders.
- Objektorientierte Programmierung ist ohnehin in manchen Aspekten philosophisch verwandt, und optimal wenn lauter veränderliche Objekte in der realen Anwendungswelt umherschwirren.
- Hat man einen simplen mathematischen Algorithmus, über 3000 Jahre konstant, dann ist triviales Runterrechnen per Prozedurale Programmierung Mittel der Wahl.
- Ansonsten gibt es in den Jahrzehnten immer mal Moden; Überbetonung von umseitig ist so eine, OOP war mal besonders hip, in den 1990ern quatschten alle von Fuzzy Logic, zwischendurch glaubte man an Expertensysteme, und alle Jahrzehnte ändert sich die Interpretation des Begriffs „Künstliche Intelligenz“.
- Heißt: Am Einleitungsabschnitt ist wenig konkret zu basteln. Artikel über Pinsel, Leinwand, Palette beginnen auch nicht mit einer Warnung, dass dies nicht zur Herstellung von Marmorskulpturen geeignet wäre.
- Ich teile auch die Ansicht von West of House, dass da keine übertriebene Lobhudelei oder hingegen eine Abwertung konkurrierender Konzepte drinsteht. Es ist eine Methodik, die bei sinnvoller Anwendung vorteilhaft ist, und die Gründe und Vorteile werden halt dargestellt.
- VG --PerfektesChaos 15:56, 8. Apr. 2022 (CEST)
- Vielen Dank für das schnelle Feedback und insbesondere für diesen Tiefgang. Ich nehme mal zur Kenntnis, daß meine Wahrnehmung nicht geteilt wird. Das ist ja auch OK. Der Vollständigkeit halber möchte ich sagen, daß schon recht viele WP-Einträge verschiedenster Gebiete auch direkt eingangs Vor- und Nachteile aufführen. Ich fand die mir hier gegebene Antwort sehr informativ und wünschte, einige der genannten Aspekte würden in den Artikel einfließen, ja, auch als Abschluß der Einleitung. Beispielsweise eben: "Funktionale Programmierung ist einerseits sehr leistungsfähig, erfordert andererseits starkes Umdenken von üblicherweise gelehrten Grundlagen und kann ggf. für manche Aufgaben auch ungeeignet sein." Wäre jetzt sicher nicht perfekt, würde dem Leser aber zu verstehen helfen, warum das nicht allgemeine Praxis ist. Aber das ist hier natürlich nur eine Einzelmeinung :-). Danke nochmal. JB. --92.193.149.202 19:12, 8. Apr. 2022 (CEST)
- Damit du noch eine zweite Antwort bekommst:
- Ich sehe es auch so wie @West of House. Es ist eine neutrale Einführung in die funktionale Programmierung. Alles was ich in der Einleitung lese ist eine Abgrenzung zu den anderen Programmierparadigmen, aber keine Aufzählung von Vorteilen insofern.
- Zur Information: Ich verdiene mein Geld mit der Programmierung und verwende primär OOP. --Herr Schroeder (Diskussion) 21:46, 8. Apr. 2022 (CEST)
- Danke sehr. Immer wieder interessant, wie man ungewollt voneinander abweichen kann. Was das Geld verdienen angeht, geht es mir ähnlich. Hab mal in F# reingeschaut, aber bisher kein Projekt gesehen, wo ich das Gefühl hatte, daß es mir was bringt. Bei Python hingegen passiert es gelegentlich, daß ich sowas verwende, wenngleich nicht oft. Haken wir das Thema ab :-). JB. --92.195.47.45 05:03, 10. Apr. 2022 (CEST)
Frust-Artikel
BearbeitenNach Lektüre dieser Diskussionsseite komme ich zu dem Ergebnis, dass dieser Artikel Viele, die mit der Materie einigermaßen vertraut sind, vor allem frustriert. Das liegt daran, dass er nicht einfach nur schlecht ist - dann könnte er nämlich in die Tonne - sondern mehrere Abschnitte in Unkenntnis der Materie verfasst wurden. Andere Abschnitte wie die Einleitung und der kategorientheoretische Teil sind ganz solide.
Im Einzelnen:
Die Abschnitte "Lambda-Kalkül" und "Funktionen höherer Ordnung" könnte man zu einer konzeptionellen Darstellung zusammen fassen. Ein Verweis auf den Lambda-Artikel reichte dabei.
Überhaupt nicht hilfreich sondern trivial-akademisch und entbehrlich ist "Abgrenzung von imperativer Programmierung".
Auch der Abschnitt "Rein funktionale Programmiersprachen", der als einziges deutsches Stück Prosa die köstliche Wortschöpfung "Wirkbehaftung" enthält (dieses Wort kennt Google nur aus diesem Artikel und dessen Kopien) hilft mir nicht weiter. Ich selbst halte es in dieer Sache auch mit dem Autor von "Funktionale Programmierung und Metaprogrammierung" (s.u.) der die Fragestellung als solche ablehnt. Schließlich können Computer nicht zustandslos sein, denn dann könnte man gar nicht mit ihnen arbeiten. Das versteht jeder sofort, der mal einen benutzt hat.
Der erste Teil des Abschnitts "Bedarfsauswertung und strikte Auswertung" hat mich ebenfalls verwirrt, und zwar das Begriffspaar strikt/nicht-strikt und dieses "(3+5)²=..=..=64"-Gedöns.
Die größte enzyklopädische Unfall ist allerdings der Abschnitt "Beispiele", denn Lernende suchen immer nach und profitieren am meisten von Beispielen. Leider aber nicht von diesen. Hier hat jeder "X"-Fan-Boy seine Version einer konzeptionell irrelevanten Kreisflächenberechnung in seiner Programmiersprache "X" vorgelegt. Keines der zentralen Konzepte der FP außer "Funktion" und "Funktionsanwendung" findet hier Verwendung. Dieser ganze Herr-Lehrer-ich-weiß-was-Abschnitt ist m.E. hilflos und wertlos. Das XSL-Beispiel ist wenigstens noch komisch, weil ich nicht wusste, dass man einen so banalen Algorithmus derart wortreich entblättern kann.
Ich bin gespannt, ob es Meinungen zu meiner (bewusst polemischen!) Darstellung gibt. --West of House (Diskussion) 16:51, 14. Dez. 2022 (CET)
- Ein paar Meinungen:
- Der "kategorientheoretische Teil" ist nicht solide.
- Die Frage, ob Computer zustandslos sind, hat mit Programmiersprachen wenig zu tun.
- --Daniel5Ko (Diskussion) 03:34, 15. Dez. 2022 (CET)
- Danke. Mal sehen was noch kommt. --West of House (Diskussion) 06:45, 15. Dez. 2022 (CET)
- Das mit den Zuständen dürfte ein einziges Missverständnis sein.
- Es geht nicht darum, ob klassische oder Quantencomputer in ihrer Hardware Zustände kennen würden.
- Es geht darum, dass bei funktionaler Programmierung die Zwischenzustände innerhalb der Evaluierung unbekannt sind. Sie stecken im System, ich komme nicht dran, und sie gehen mich auch nichts an, und ich könnte auch nichts damit anfangen.
- Es gibt nur die Startwerte und das Resultat.
- Das ist anders als bei Prozeduren, wo ich zu Beginn und zum Ende einer Funktion Parameter und Rückgabewert loggen könnte. Weil ich den Algorithmus kenne, kann ich daran verfolgen, was genau meine Prozedur abarbeitet. Das klappt hier nicht.
- Ich finde die Zusammenstellung der Beispiele sehr informativ.
- Sie entspricht den Hallo-Welt-Beispielen und gibt einen Eindruck in Syntax und Notation an einem trivialen und übersichtlichen Beispielproblem. So wie „Hallo Welt“ sagen auch kein Riesending wäre, aber ein Assemblerprogramm dazu zu bringen das auf einen Monitor zu schreiben ist eine Herausforderung.
- Ich selbst schreibe seit 40 Jahren mit Lisp und Tücke, äh, Lambda, und kann mit Haskell umgehen. Die Menge der Probleme, bei denen ich sowas einsetzen und dauerhaft Anderen zumuten würde, ist jedoch mikroskopisch.
- Den Abschnitt mit der Abgrenzung von imperativen, prozeduralen Programmierung finde ich extrem wichtig. Es ist die wesentliche Hürde, die man erstmal überwinden muss – vergiss alle deine Vorstellungen, die du aus der prozeduralen Welt mitbringst, und fange bei Null an neu zu denken. Sonst wird das nix.
- Nebenbei bemerkt ist „Zustandslosigkeit“ ein Riesenthema in der IT und hat nichts mit Computer-Hardware zu tun.
- VG --PerfektesChaos 17:58, 15. Dez. 2022 (CET)
- Das mit den Zuständen dürfte ein einziges Missverständnis sein.
- Vielleicht noch zur Ergänzung, um die Kritik am "kategorientheoretischen Teil" etwas konkreter werden zu lassen: Was ein Katamorphismus ist, lässt sich ja recht kurz definieren ([2]): Gegeben einen Endofunktor , ist ein Katamorphismus einfach der einzige F-Algebra-Homomorphismus von der initialen F-Algebra (wir nehmen mal an, dass es die gibt) zu einer anderen F-Algebra.
- Tatsächlich dual dazu wäre: ein Anamorphismus ist der einzige F-Koalgebra-Homomorphismus von einer anderen F-Koalgebra zur terminalen F-Koalgebra.
- Nun stimmen in den meisten Kategorien die Trägerobjekte von initialen F-Algebren und terminalen F-Koalgebren natürlich nicht überein.
- Für eine Menge hätten wir beim Funktor für die A-Listensignatur, in einerseits die Menge der endlichen Listen über und andererseits die Menge der endlichen oder unendlichen Listen über .
- Die Kategorie(nklasse), über die man spricht, wenn man in Lean 3 nur "normale" Funktionsdefinitionen verwendet, ist ausreichend -like, um auf die Unterschiede aufmerksam zu werden:
def list.fold{A S : Type}(f : option (A × S) → S): list A → S | [] := f none | (a::as) := f $ some (a, list.fold as)
- Entsprechendes mit
unfold
,geht nicht. Man muss ein paar zusätzliche Forderungen stellen, wenn man tatsächlichdef list.unfold{A S : Type}(f : S → option (A × S)): S → list A := ???
list A
als Ergebnis haben will, etwa etwas mit einer wohlfundierten Relation: def list.unfold{A S : Type}{R : S → S → Prop} (wf: well_founded R) (f : S → option (A × S))(M : ∀ {s as}, f s = some as → R as.2 s): S → list A := wf.fix $ λ s rec, begin cases e: f s with as e, exact [], exact as.1 :: rec as.2 (M e), end
- Oder man verwendet statt (
list A
) eben passendererweise (hierstream A
): def stream(A : Type) := {f : ℕ → option A // ∀ n, f n = none → f (n+1) = none } -- oder wie auch immer man das Konzept formalisieren möchte. def stream.unfold{A S : Type}(α : S → option(A × S)): S → stream A := [...]
- Das geht.
- Klar, wenn man zu Kategorien übergeht, in denen die Pfeile partielle Funktionen sind (hier sind aber auch mindestens zwei Ausprägungen möglich),
- werden manchmal zumindest die Trägerobjekte vereinigt (in Haskell etwa gibt es soetwas wie eigentlich gar nicht, in ML schon; ein
unfold
in ML kann aber auch nicht Totalität garantieren, und dann wird anderes komisch, etc.). --Daniel5Ko (Diskussion) 02:00, 16. Dez. 2022 (CET)
Imperativ!
Bearbeiten„Sei ein beliebiger Datentyp“ schreit doch geradezu nach einem „!“! 🥸 Mir scheint, da wurde etwas zu sehr rekursiv wegoptimiert. 🥸 (nicht signierter Beitrag von 84.166.43.135 (Diskussion) 01:13, 31. Mär. 2024 (CET))