Frage

Ich bin mir nicht sicher, wie viel dies unter "Programmierung" gegen "Programm Sprachdesign" fällt. Aber das Problem ist Folgendes:

Sagen Sie, aus Einfachheit halber haben wir zwei "spezielle" Listen/Arrays/Vektoren/wie auch immer wir einfach "Ports" nennen stdIn und ein anderer stdOut. Diese repräsentieren jeweils jeweils

  • Alle Benutzereingaben, die dem Programm in der Dauer des Programms gegeben wurden
  • Die gesamte Ausgabe, die während der Dauer des Programms an das Terminal geschrieben wurde

In von Haskell inspiriertem Pseudocode sollte es dann möglich sein, dieses vollständig deklarative Programm zu erstellen:

 let stdOut =   ["please input a number", 
                "and please input another number", 
                "The product of both numbers is: " ++ stdIn[0] * stdIn[1]]

Das würde das erwartete tun, nach zwei Zahlen fragen und ihr Produkt ausdrucken. Der Trick ist, dass Stdout die Liste der Zeichenfolgen darstellt, die beim Abschluss des Programms an das Terminal geschrieben wurden, und die Liste der Eingabebestnen. Geben Sie Fehler ein und die Tatsache, dass es einen Schutz geben muss, um nur die nächste Zeile zu drucken, nachdem eine neue Zeile zum Einfachheit halber hier beiseite gelassen wurde. Es ist wahrscheinlich leicht genug, dies zu lösen.

Bevor ich diese Idee umsetzte, gibt es also irgendwelche Fallstricke, die ich übersehen habe? Mir ist kein ähnliches Konstrukt bewusst, sodass es naiv ist, nicht zu berücksichtigen, dass es eine offensichtliche Gefahr gibt, die ich übersehen habe.

Ansonsten weiß ich das natürlich:

 let stdOut =   [stdIn[50],"Hello, World!"]

Wäre ein Fehler, wenn diese Ergebnisse wie oben in ähnlicher Weise verwoben werden müssen.

War es hilfreich?

Lösung

Ein ähnlicher Ansatz wurde in frühen Versionen von Haskell verwendet, mit der Ausnahme, dass die Elemente der Stdin- und Stdout-Kanäle keine Zeichenfolgen waren, sondern generische IO-Aktionen-tatsächlich wurden Eingabe und Ausgabe auf "Antwort" und "Anfrage" verallgemeinert. Solange beide Kanäle faul sind (dh sie sind tatsächlich "Iteratoren" oder "Enumeratoren"), kann die Laufzeit einfach den Anforderungskanal betreten, auf jede Anfrage reagieren und entsprechende Antworten auf den Antwortkanal stellen. Leider war das System sehr schwer zu bedienen und wurde zugunsten des monadischen IO verschrottet. Siehe diese Papiere:

  • Hudak, P. und Sundaresh, R. über die Ausdruckskraft rein funktionierender E/A-Systeme. Technik. Rep. Yaleu/DCS/RR-665, Abteilung für Informatik, Yale University, März 1989.
  • Peyton Jones, S. Angriff auf den unangenehmen Kader: Monadische Eingabe/Ausgabe, Parallelität, Ausnahmen und fremdsprachige Anrufe in Haskell. In Engineering Theories of Software Construction, 2002, S. 47-96.

Andere Tipps

Der Ansatz, den Sie beschreiben, klingt wie "Dialoge". In ihrer preisgekrönten Zeitung von 1993 Imperative funktionelle Programmierung, Phil Wadler und Simon Peyton Jones geben einige Beispiele, in denen Dialoge wirklich nicht sehr gut funktionieren, und sie erklären, warum monadische I/O besser ist.

Ich sehe nicht, wie Sie sie unter Berücksichtigung dieses Beispiels im Vergleich zu Ihrem eigenen weben werden:

let stdOut =   ["Welcome to the program which multiplies.",
                "please input a number", 
                "and please input another number", 
                "The product of both numbers is: " ++ stdIn[0] * stdIn[1]]

Sollte das Programm auf die Nummer auffordern, die von dargestellt wird durch stdIn[0] Nachdem Sie eine Zeile (wie in Ihrem Beispiel) oder zwei Zeilen ausgegeben haben? Wenn der Index 0 repräsentiert den 0. Eingang von Stdin, dann scheint es etwas Ähnliches zu sein:

let stdOut =   ["Welcome to the program which multiplies.",
                "please input a number",
                some_annotation(stdIn[0]),
                "and please input another number", 
                some_annotation(stdIn[1]),
                "The product of both numbers is: " ++ stdIn[0] * stdIn[1]]

ist erforderlich, um den Zeitpunkt der Ausgabe und Eingabe zu koordinieren.

Ich mag deine Idee. Ersetzen some_annotation Mit Ihrer Präferenz, vielleicht etwas ähnliches "synchronisieren"? Ich konnte mir das einschneidende Wort dafür nicht einfallen lassen.

Dieser Ansatz scheint der "offensichtlichste" Weg zu sein, um einem reinen λ-Kalkulus I/O hinzuzufügen, und andere Menschen haben erwähnt, dass in Haskell und Miranda etwas in dieser Richtung vor Gericht gestellt wurde.

Ich bin mir jedoch einer Sprache bewusst, die nicht auf einem λ-Kalkulus basiert und das immer noch ein sehr ähnliches System verwendet:

Wie gehe ich in einer Sprache ohne Nebenwirkungen mit Eingabe und Ausgabe um? In gewissem Sinne sind Input und Ausgabe keine Nebenwirkungen. Sie sind sozusagen sozusagen, Front- und Rückwirkungen. (...) [Ein Programm ist] eine Funktion aus dem Speicherplatz möglicher Eingänge zum Speicherplatz möglicher Ausgänge.

Eingangs- und Ausgangsströme werden als Listen natürlicher Zahlen von 0 bis 255 dargestellt, die jeweils einem Byte entsprechen. Das Dateiende wird durch den Wert 256 dargestellt, nicht bis zum Ende der Liste. (Dies liegt daran, dass es oft einfacher ist, mit EOF als Charakter als als Sonderfall umzugehen. Trotzdem frage ich mich, ob es nicht besser wäre, das Ende der List zu verwenden.)

(...)

Es ist nicht schwierig, interaktive Programme zu schreiben (...) [), aber technisch gesehen ist dies eine Sünde. .

(...) Die offensichtlichste Art, dieses spezielle Programm zu schreiben, besteht darin, zusammen mit dem "Hallo, [Namen]!" Zeichenfolge in einem Ausdruck, der nach Erhalt einer neuen Linie konditioniert ist. Wenn Sie dies tun, sind Sie in Sicherheit, da ein Bewerter keine Möglichkeit gibt, im Voraus zu beweisen, dass der Benutzer jemals eine neue Linie eingeben wird.

(...)

Es gibt also kein praktisches Problem mit interaktiver Software. Trotzdem hat die Art und Weise, wie der zweite Fall verhindert wird, etwas Unangenehmes. Ein referentiell transparentes Programm sollte sich nicht auf eine faule Bewertung verlassen müssen, um ordnungsgemäß zu arbeiten.

Wie kann man diesem moralischen Dilemma entkommen? Der schwierige Weg besteht darin, zu einem anspruchsvolleren E/A -System zu wechseln, möglicherweise basierend auf Haskells, in dem Eingang und Ausgabe explizit synchronisiert sind. Ich bin eher abgehoben, da ich die Einfachheit des aktuellen Systems sehr bevorzuge. Der einfache Ausweg besteht darin, Batch -Programme zu schreiben, die interaktiv gut funktionieren. Dies geht hauptsächlich nur darum, den Benutzer nicht zu fordern.

Vielleicht würden Sie gerne etwas programmieren Faul k?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top