Gibt es wirklich Unveränderlichkeit in der funktionalen Programmierung?

9

Obwohl ich in meinem täglichen Leben als Programmierer arbeite und alle trendigen Sprachen (Python, Java, C usw.) verwende, habe ich immer noch keine klare Vorstellung davon, was funktionale Programmierung ist. Nach dem, was ich gelesen habe, ist eine Eigenschaft von Funktionssprachen, dass Datenstrukturen unveränderlich sind . Für mich allein wirft dies viele Fragen auf. Aber zuerst werde ich ein bisschen von dem schreiben, was ich von Unveränderlichkeit verstehe, und wenn ich falsch liege, kannst du mich gerne korrigieren.

Mein Verständnis von Unveränderlichkeit:

  • Wenn ein Programm gestartet wird, hat es feste Datenstrukturen mit festen Daten
  • Man kann diesen Strukturen keine neuen Daten hinzufügen
  • Der Code enthält keine Variablen
  • Sie können lediglich aus den bereits vorhandenen oder aktuell berechneten Daten "kopieren"
  • Aus all diesen Gründen erhöht die Unveränderlichkeit die Komplexität eines Programms erheblich

Meine Fragen:

  1. Wenn Datenstrukturen so bleiben sollen, wie sie sind (unveränderlich), wie zum Teufel fügt jemand ein neues Element in eine Liste ein?
  2. Was bringt es, ein Programm zu haben, das keine neuen Daten erhalten kann? Angenommen, Sie haben einen Sensor an Ihren Computer angeschlossen, der dem Programm Daten zuführen möchte. Würde das bedeuten, dass wir die eingehenden Daten nirgendwo speichern können?
  3. Wie ist funktionale Programmierung in diesem Fall gut für maschinelles Lernen? Denn maschinelles Lernen basiert auf der Annahme, die "Wahrnehmung" der Dinge durch das Programm zu aktualisieren und so neue Daten zu speichern.
Pithikos
quelle
2
Ich stimme Ihnen nicht zu, wenn Sie sagen, dass der Funktionscode keine Variablen enthält. Es gibt Variablen im mathematischen Sinne von „Eine Größe, die einen beliebigen Wert annehmen kann“. Sie sind zwar nicht veränderlich , aber auch nicht in der Mathematik.
Édouard
1
Ich denke, Ihre Verwirrung liegt darin, dass Sie abstrakt über funktionale Sprachen nachdenken. Nehmen Sie einfach ein Programm in Haskell - z. B. ein Programm, das eine Liste von Zahlen von der Konsole liest, sie schnell sortiert und ausgibt - und finden Sie heraus, wie es funktioniert und wie es Ihren Verdacht widerlegt. Es gibt keine Möglichkeit, Dinge wirklich zu klären, ohne Beispiele für tatsächliche Programme zu betrachten, anstatt zu philosophieren. In jedem Haskell-Tutorial finden Sie zahlreiche Programme.
jkff
@jkff Was versuchst du zu sagen? Dieser Haskel hat nicht funktionale Merkmale. Die Frage betrifft nicht Haskell, sondern die funktionale Programmierung. Oder behaupten Sie, dass alles funktionsfähig ist? Wie? Also, was sollte falsch sein am Philosophieren, wie Sie sagen. Inwiefern ist Abstraktion verwirrend? Die OP-Frage ist sehr vernünftig.
Babou
@babou Ich versuche zu sagen, dass der beste Weg zu verstehen, wie eine rein funktionale Programmiersprache Algorithmen und Datenstrukturen effizient implementieren kann, darin besteht, Beispiele für Algorithmen und Datenstrukturen zu betrachten, die effizient in einer funktionalen Programmiersprache implementiert sind. Es scheint mir, dass OP versucht hat zu verstehen, wie es konzeptionell möglich ist - ich denke, der schnellste Weg, dies zu verstehen, besteht darin, Beispiele zu betrachten, anstatt eine konzeptionelle Erklärung zu lesen, egal wie detailliert.
JKFF
Eine Möglichkeit, die funktionale Programmierung zu betrachten, besteht darin, zu sagen, dass sie ohne Nebenwirkungen programmiert. Sie können dies in der "trendigen" Sprache Ihrer Wahl tun. Vermeiden Sie nur nicht alle Neuzuweisungen: In Java sind beispielsweise alle Ihre Variablen endgültig und alle Ihre Methoden schreibgeschützt.
Reinierpost

Antworten:

10

Wenn ein Programm gestartet wird, hat es feste Datenstrukturen mit festen Daten

Dies ist ein Missverständnis. Es hat eine feste Form und einen festen Satz von Umschreiberegeln, aber diese Umschreiberegeln können in etwas viel Größeres explodieren. Zum Beispiel wird der Ausdruck [1..100000000] in Haskell durch eine sehr kleine Menge Code dargestellt, aber seine normale Form ist massiv.

Man kann diesen Strukturen keine neuen Daten hinzufügen

Ja und nein. Die rein funktionale Teilmenge einer Sprache wie Haskell oder ML kann keine Daten von der Außenwelt abrufen, aber jede Sprache für die praktische Programmierung verfügt über einen Mechanismus zum Einfügen von Daten von der Außenwelt in die rein funktionale Teilmenge. In Haskell wird dies sehr sorgfältig gemacht, aber in ML können Sie dies tun, wann immer Sie wollen.

Der Code enthält keine Variablen

Dies ist ziemlich wahr, aber verwechseln Sie dies nicht mit der Idee, dass nichts benannt werden kann. Sie benennen ständig nützliche Ausdrücke und verwenden sie ständig wieder. Auch ML und Haskell, jedes Lisp, das ich ausprobiert habe, und Hybriden wie Scala haben alle die Möglichkeit, Variablen zu erstellen. Sie werden einfach nicht häufig verwendet. Und wieder haben die rein funktionalen Teilmengen solcher Sprachen sie nicht.

Sie können lediglich aus den bereits vorhandenen oder aktuell berechneten Daten "kopieren"

Sie können die Berechnung durch Reduzieren auf die normale Form durchführen. Am besten schreiben Sie wahrscheinlich Programme in einer funktionalen Sprache, um zu sehen, wie sie tatsächlich Berechnungen durchführen.

Zum Beispiel ist "sum [1..1000]" keine Berechnung, die ich durchführen möchte, aber sie wird von Haskell recht einfach durchgeführt. Wir gaben ihm einen kleinen Ausdruck, der für uns von Bedeutung war, und Haskell gab uns die entsprechende Nummer. Es führt also definitiv eine Berechnung durch.

Wenn Datenstrukturen so bleiben sollen, wie sie sind (unveränderlich), wie zum Teufel fügt jemand ein neues Element in eine Liste ein?

Sie fügen einer Liste kein neues Element hinzu, sondern erstellen aus der alten eine neue Liste. Da die alte nicht mutiert werden kann, ist es absolut sicher, sie in der neuen Liste zu verwenden oder wo immer Sie möchten. In diesem Schema können viel mehr Daten sicher geteilt werden.

Was bringt es, ein Programm zu haben, das keine neuen Daten erhalten kann? Angenommen, Sie haben einen Sensor an Ihren Computer angeschlossen, der dem Programm Daten zuführen möchte. Würde das bedeuten, dass wir die eingehenden Daten nirgendwo speichern können?

In Bezug auf Benutzereingaben kann jede praktische Programmiersprache Benutzereingaben erhalten. Das passiert. Es gibt jedoch eine voll funktionsfähige Teilmenge dieser Sprachen, in die Sie den größten Teil Ihres Codes schreiben, und Sie profitieren auf diese Weise von den Vorteilen.

Wie ist funktionale Programmierung in diesem Fall gut für maschinelles Lernen? Denn maschinelles Lernen basiert auf der Annahme, die "Wahrnehmung" der Dinge durch das Programm zu aktualisieren und so neue Daten zu speichern.

Dies wäre beim aktiven Lernen der Fall, aber das meiste maschinelle Lernen, mit dem ich gearbeitet habe (ich arbeite als Code-Affe in einer maschinellen Lerngruppe und habe dies einige Jahre lang getan), hat einen einmaligen Lernprozess, bei dem alle Trainingsdaten geladen werden sofort ein. Aber für aktives Lernen kann man Dinge nicht 100% rein funktional machen. Sie müssen einige Daten aus der Außenwelt einlesen.

Jake
quelle
Ich habe das Gefühl, Sie haben den wohl wichtigsten Punkt in @ Pithikos 'Beitrag ignoriert, nämlich das Platzproblem - Funktionsprogramme belegen mehr Platz als zwingende (Sie können keine In-Place-Algorithmen und dergleichen schreiben)
user541686
2
Das stimmt einfach nicht. Der Mangel an Mutation wird größtenteils durch das Teilen ausgeglichen, und obendrein ist der Größenunterschied, auf den Sie sich beziehen, bei modernen Compilern erstaunlich gering. Der meiste Code in Listen in Haskell ist effizient vorhanden oder verwendet überhaupt keinen Speicher.
Jake
1
Ich denke, Sie stellen ML etwas falsch dar. Ja, E / A kann überall stattfinden, aber die Art und Weise, wie neue Informationen in vorhandene Strukturen eingeführt werden, wird streng kontrolliert.
dfeuer
@Pithikos, Es gibt überall Variablen; Sie unterscheiden sich nur von dem, was Sie gewohnt sind, wie Édouard angedeutet hat. Und die Dinge werden ständig zugeteilt und Müll gesammelt. Sobald Sie tatsächlich mit der funktionalen Programmierung beginnen, erhalten Sie ein besseres Gefühl dafür, wie es tatsächlich funktioniert.
dfeuer
1
Es gibt zwar Algorithmen, die keine rein funktionale Implementierung mit der gleichen zeitlichen Komplexität wie die bekannteste imperative Implementierung haben - z. B. die Union-Find-Datenstruktur (und, ähm, Arrays :)). Ich stelle mir vor, dass es auch solche Fälle für den Weltraum gibt Komplexität. Dies sind jedoch Ausnahmen - die meisten gängigen Algorithmen / Datenstrukturen haben Implementierungen mit gleicher zeitlicher und räumlicher Komplexität. Es ist eine subjektive Frage des Programmierstils und (zu einem konstanten Faktor) der Qualität des Compilers.
jkff
4

Unveränderlichkeit oder Veränderlichkeit sind keine Konzepte, die in der funktionalen Programmierung sinnvoll sind.

Der rechnerische Kontext

Dies ist eine sehr gute Frage, die eine interessante Fortsetzung (kein Duplikat) einer anderen aktuellen Frage darstellt: Was ist der Unterschied zwischen Zuordnung, Bewertung und Namensbindung?

Anstatt einzeln auf Ihre Aussagen zu antworten, versuche ich hier, Ihnen einen strukturierten Überblick darüber zu geben, worum es geht.

Es gibt verschiedene Punkte, die berücksichtigt werden müssen, um Sie zu beantworten, darunter:

  • Was ist ein Berechnungsmodell und welche Konzepte sind für ein bestimmtes Modell sinnvoll?

  • Welche Bedeutung haben die von Ihnen verwendeten Wörter und wie hängt sie vom Kontext ab?

Der funktionale Programmierstil scheint albern, weil Sie ihn mit einem zwingenden Programmiererauge sehen. Aber es ist ein anderes Paradigma, und Ihre imperativen Konzepte und Wahrnehmungen sind fremd und fehl am Platz. Die Compiler haben keine derartigen Vorurteile.

Die Endschlussfolgerung ist jedoch, dass es möglich ist, Programme auf rein funktionale Weise zu schreiben, auch für maschinelles Lernen. Die funktionale Programmierung hat jedoch nicht das Konzept, Daten zu speichern. Ich scheine in diesem Punkt mit anderen Antworten nicht einverstanden zu sein.

In der Hoffnung werden einige trotz der Länge dieser Antwort interessiert sein.

Computerparadigmen

Die Frage betrifft die funktionale Programmierung (auch bekannt als anwendungsbezogene Programmierung), ein spezifisches Berechnungsmodell, dessen theoretischer und einfachster Vertreter die Lambda-Rechnung ist.

Wenn Sie auf einem theoretischen Niveau bleiben, gibt es viele Berechnungsmodelle: die Turing-Maschine (TM), die RAM-Maschine und andere , die Lambda-Rechnung, die kombinatorische Logik, die rekursive Funktionstheorie, Semi-Thue-Systeme usw. Je leistungsfähiger die Berechnung Modelle haben sich in Bezug auf das, was sie ansprechen können, als gleichwertig erwiesen, und das ist der Kern der Church-Turing-These .

Ein wichtiges Konzept ist die gegenseitige Reduzierung von Modellen, die die Grundlage für die Ermittlung der Äquivalenzen bilden, die zur These von Church-Turing führen. Aus Sicht des Programmierers ist das Reduzieren eines Modells auf ein anderes so ziemlich das, was normalerweise als Compiler bezeichnet wird. Wenn Sie die Logikprogrammierung als Berechnungsmodell verwenden, unterscheidet sie sich erheblich von dem Modell des PCs, den Sie in einem Geschäft gekauft haben, und der Compiler übersetzt in Logikprogrammiersprache geschriebene Programme in das von Ihrem PC dargestellte Rechenmodell (ziemlich genau) der RAM-Computer).

Dies bedeutet jedoch nicht, dass die beiden Modelle auf die gleiche Weise vorgehen oder dass ein für eines sinnvolles Konzept als solches auf ein anderes übertragen werden kann. Typischerweise hat ein Berechnungsschritt in einem TM wenig Beziehung zu einem ( -) - Reduktionsschritt in Lambda Calculus, obwohl sie interübersetzbar sind. Das Konzept der optimalen Bewertung der Lambda-Expression ist weit entfernt von Komplexitätsproblemen in TM-Modellen.β

In der Praxis tendieren die von uns verwendeten Programmiersprachen dazu, Konzepte unterschiedlicher theoretischer Herkunft zu mischen und dies so zu versuchen, dass ausgewählte Teile eines Programms gegebenenfalls von den Eigenschaften eines Modells profitieren können. In ähnlicher Weise können Personen, die Systeme erstellen, unterschiedliche Sprachen für unterschiedliche Komponenten auswählen, um die Sprache am besten an die jeweilige Aufgabe anzupassen.

Daher sehen Sie selten ein Programmierparadigma in einem reinen Zustand in einer Programmiersprache. Programmiersprachen werden immer noch nach dem vorherrschenden Paradigma klassifiziert, aber die Eigenschaften der Sprache können beeinträchtigt werden, wenn Konzepte aus anderen Paradigmen beteiligt sind, wodurch häufig Unterscheidungen und konzeptionelle Probleme verwischt werden.

Normalerweise werden Sprachen wie Haskell und ML oder CAML als funktional angesehen, aber sie können zwingendes Verhalten zulassen ... Warum sollte man sonst von der " rein funktionalen Teilmenge " sprechen ?

Dann kann man behaupten, dass Sie dies oder jenes in meiner funktionalen Programmiersprache tun können, aber es beantwortet nicht wirklich eine Frage zur funktionalen Programmierung, wenn es sich auf das stützt, was als außerfunktional angesehen werden kann.

Die Antworten sollten sich ohne die Extras genauer auf ein bestimmtes Paradigma beziehen.

Was ist eine Variable?

Ein weiteres Problem ist die Verwendung von Terminologie. In der Mathematik ist eine Variable eine Entität, die in einem bestimmten Bereich für einen unbestimmten Wert steht. Es wird für verschiedene Zwecke verwendet. In einer Gleichung verwendet, kann es für jeden Wert stehen, so dass die Gleichung verifiziert wird. Diese Vision wird in der Logikprogrammierung unter dem Namen " logische Variable " verwendet, wahrscheinlich weil die Namensvariable bereits bei der Entwicklung der Logikprogrammierung eine andere Bedeutung hatte.

In der traditionellen imperativen Programmierung wird eine Variable als eine Art Container (oder Speicherort) verstanden, der die Darstellung eines Werts speichern und möglicherweise seinen aktuellen Wert durch einen anderen ersetzen kann.

In der funktionalen Programmierung hat eine Variable den gleichen Zweck wie in der Mathematik als Platzhalter für einen Wert, der noch bereitgestellt werden muss. In der traditionellen imperativen Programmierung wird diese Rolle tatsächlich von Konstanten gespielt (nicht zu verwechseln mit Literalen, bei denen es sich um bestimmte Werte handelt, die mit einer für diesen Wertebereich spezifischen Notation ausgedrückt werden, wie z. B. 123, true, ["abdcz", 3.14]).

Variablen jeglicher Art sowie Konstanten können durch Bezeichner dargestellt werden.

Der Wert der imperativen Variablen kann geändert werden, und das ist die Grundlage für die Veränderlichkeit. Die Funktionsvariable kann nicht.

Programmiersprachen ermöglichen normalerweise das Erstellen größerer Entitäten aus den kleineren in der Sprache.

Imperative Sprachen ermöglichen es solchen Konstrukten, Variablen einzuschließen, und das gibt Ihnen veränderbare Daten.

Wie man ein Programm liest

Ein Programm ist im Grunde eine abstrakte Beschreibung Ihres Algorithmus in einer Sprache, sei es ein pragmatisches Design oder eine paradigmatisch reine Sprache.

Im Prinzip können Sie jede Aussage für das nehmen, was sie abstrakt bedeuten soll. Dann übersetzt der Compiler dies in eine geeignete Form, die der Computer ausführen kann, aber das ist in erster Näherung nicht Ihr Problem.

Natürlich ist die Realität etwas härter, und es ist oft gut, eine Vorstellung davon zu haben, was passiert, um Strukturen zu vermeiden, mit denen der Compiler für eine effiziente Ausführung nicht umgehen kann. Aber das ist schon eine Optimierung ... für die Compiler sehr gut sein können, oft besser als Programmierer.

Funktionale Programmierung und Veränderlichkeit

Die Veränderlichkeit basiert auf der Existenz imperativer Variablen, die Werte enthalten können, die durch Zuweisung geändert werden müssen. Da diese in der funktionalen Programmierung nicht vorhanden sind, kann alles als unveränderlich angesehen werden.

Die Funktionsprogrammierung befasst sich ausschließlich mit Werten.

Ihre ersten vier Aussagen zur Unveränderlichkeit sind größtenteils richtig, beschreiben aber mit zwingender Sicht etwas, das nicht zwingend ist. Es ist ein bisschen so, als würde man mit Farben in einer Welt beschreiben, in der jeder blind ist. Sie verwenden Konzepte, die der funktionalen Programmierung fremd sind.

Sie haben nur reine Werte, und ein Array von Ganzzahlen ist ein reiner Wert. Um ein anderes Array zu erhalten, das sich nur in einem Element unterscheidet, müssen Sie einen anderen Array-Wert verwenden. Das Ändern eines Elements ist nur ein Konzept, das in diesem Kontext nicht existiert. Möglicherweise haben Sie eine Funktion, die ein Array und einige Indizes als Argument hat und ein Ergebnis zurückgibt, das nahezu identisch ist und sich nur dort unterscheidet, wo dies durch die Indizes angezeigt wird. Es ist jedoch immer noch ein unabhängiger Array-Wert. Wie diese Werte dargestellt werden, ist nicht Ihr Problem. Vielleicht "teilen" sie viel in der zwingenden Übersetzung für den Computer ... aber das ist die Aufgabe des Compilers ... und Sie möchten nicht einmal wissen, für welche Art von Maschinenarchitektur er kompiliert.

Sie kopieren keine Werte (es macht keinen Sinn, es ist ein Fremdwort). Sie verwenden nur Werte, die in den Domänen vorhanden sind, die Sie in Ihrem Programm definiert haben. Entweder beschreiben Sie sie (als Literale) oder sie sind das Ergebnis der Anwendung einer Funktion auf einige andere Werte. Sie können ihnen einen Namen geben (wodurch eine Konstante definiert wird), um sicherzustellen, dass derselbe Wert an verschiedenen Stellen im Programm verwendet wird. Beachten Sie, dass die Funktionsanwendung nicht als Berechnung, sondern als Ergebnis der Anwendung auf die angegebenen Argumente wahrgenommen werden sollte. Schreiben 5+2oder Schreiben ist 7gleich. Was mit dem vorherigen Absatz übereinstimmt.

Es gibt keine zwingenden Variablen. Eine Zuordnung ist nicht möglich. Sie können Namen nur an Werte binden (um Konstanten zu bilden), im Gegensatz zu imperativen Sprachen, in denen Sie Namen an zuweisbare Variablen binden können.

Ob dies mit Kosten verbunden ist, ist völlig unklar. Zum einen betrifft Ihr Hinweis auf Komplexität zwingende Paradigmen. Es ist nicht als solches für die funktionale Programmierung definiert, es sei denn, Sie lesen Ihr funktionales Programm als ein zwingendes, was nicht die Absicht des Designers ist. In der Tat soll die Funktionsansicht Sie nicht über solche Probleme beunruhigen und sich auf das konzentrieren, was berechnet wird. Es ist ein bisschen wie Spezifikation versus Implementierung.

Der Compiler muss sich um die Implementierung kümmern und klug genug sein, um das, was zu tun ist, am besten an die Hardware anzupassen, die es tun wird, was auch immer es ist.

Ich sage nicht, dass sich Programmierer darüber niemals Sorgen machen. Ich sage auch nicht, dass Programmiersprachen und Compilertechnologie so ausgereift sind, wie wir es uns wünschen könnten.

Beantwortung der Fragen

  1. Sie ändern keinen vorhandenen Wert (Alien-Konzept), sondern berechnen neue Werte, die sich bei Bedarf unterscheiden, möglicherweise indem Sie ein zusätzliches Element als Liste verwenden.

  2. Das Programm kann neue Daten erhalten. Der springende Punkt ist, wie Sie das in der Sprache ausdrücken. Sie können beispielsweise davon ausgehen, dass das Programm mit einem bestimmten Wert arbeitet, der möglicherweise unbegrenzt groß ist und als Eingabestream bezeichnet wird. Es ist ein Wert, der dort sitzen soll (ob es bereits vollständig bekannt ist oder nicht, ist nicht Ihr Problem). Dann haben Sie eine Funktion, die ein Paar zurückgibt, das aus dem ersten Element des Streams und dem Rest des Streams besteht.

    Sie können dies verwenden, um Netzwerke von Kommunikationskomponenten auf rein anwendungsbezogene Weise aufzubauen (Coroutinen).

  3. Maschinelles Lernen ist nur ein weiteres Problem, wenn Sie Daten sammeln und Werte ändern müssen. In der funktionalen Programmierung tun Sie das nicht: Sie berechnen nur neue Werte, die sich entsprechend den Trainingsdaten entsprechend unterscheiden. Die resultierende Maschine funktioniert ebenfalls. Was Sie sich Sorgen machen, ist die Berechnung der Zeit- und Raumeffizienz. Aber auch dies ist ein anderes Problem, das idealerweise vom Compiler behandelt werden sollte.

Schlussbemerkungen

Aus den Kommentaren oder anderen Antworten geht klar hervor, dass praktische funktionale Programmiersprachen nicht rein funktional sind. Dies spiegelt die Tatsache wider, dass unsere Technologie noch verbessert werden muss, insbesondere beim Kompilieren.

Ist es möglich, rein anwendungsbezogen zu schreiben? Die Antwort ist seit ungefähr 40 Jahren bekannt und lautet "Ja". Der eigentliche Zweck der Denotationssemantik, wie sie in den 1970er Jahren auftrat, bestand genau darin, Sprachen in einen rein funktionalen Stil zu übersetzen (zu kompilieren), der mathematisch besser verstanden und daher als bessere Grundlage für die Definition der Semantik von Programmen angesehen wurde.

Das Interessante daran ist, dass die imperative Programmierstruktur, einschließlich der Variablen, durch Einführung geeigneter Wertebereiche wie eines Datenspeichers in einen funktionalen Stil übersetzt werden kann. Und trotz des funktionalen Stils bleibt es dem Code der tatsächlichen Compiler, die im imperativen Stil geschrieben sind, überraschend ähnlich.

babou
quelle
0

Es ist ein Missverständnis, dass funktionale Programme keine Daten speichern können, und ich denke nicht, dass Jakes Antwort dies wirklich sehr gut erklärt hat.

Funktionsprogramme sind wie alle Programme Funktionen, die Ganzzahlen Ganzzahlen zuordnen. Jedes zwingende Programm, das mit veränderlichen Datenstrukturen arbeitet, hat ein funktionales Gegenstück. Dies ist nur ein weiteres Mittel, um das gleiche Ziel zu erreichen.

Die funktionale Art des Speicherns von Experimentdaten aus einer Quelle würde darin bestehen, die Speicherfunktion mit der Datenstruktur als Argument aufzurufen und eine Verkettung der vorhandenen Datenstruktur und der neuen Daten auszugeben, und somit werden Daten ohne den Begriff veränderlicher Datenstrukturen gespeichert.

Aus eigener Erfahrung denke ich, dass das Konzept unveränderlicher Datenstrukturen konventionelle Entwickler zu der Annahme veranlasst, dass es bestimmte Dinge gibt, die in einer funktionalen Umgebung unpraktisch oder sogar unmöglich sind. Das ist nicht der Fall.

Jeppe Hartmund
quelle
"Funktionsprogramme sind wie alle Programme wirklich Funktionen, die Ganzzahlen Ganzzahlen zuordnen." Wie ist beispielsweise Minecraft wirklich eine Funktion, die Ganzzahlen Ganzzahlen zuordnet?
David Richerby
Leicht. Jedes Byte kann als binäre Ganzzahl interpretiert werden. Ein Status in einem Computer ist eine Sammlung von Bytes. Ein Programm, sogar Minecraft, manipuliert einen Computerstatus und ordnet ihn von einem Status einem anderen zu.
Jeppe Hartmund
Benutzereingaben scheinen nicht in diese Welt zu passen.
David Richerby
Benutzereingaben sind Teil eines Computerstatus. Es existiert nicht nur auf Ihrem Bildschirm.
Jeppe Hartmund