Frage

Ich versuche Sinn des Beispielcodes zu machen hier (Beispiele unten). Ich verstehe nicht, dass parametrisieren konstruieren. Die Dokumentation für sie sind hier , aber sie helfen nicht. Was ist zu tun?

War es hilfreich?

Lösung

parameterize wird verwendet, um Werte zu haben, die „dynamisch scoped“ werden. Sie erhalten einen Parameter mit make-parameter. Der Parameter selbst als Funktion verhält: nennen es ohne Ein- und Sie seinen Wert erhalten, rufen Sie es mit einem Wert und es wird der Wert festgelegt. Zum Beispiel:

> (define p (make-parameter "blah"))
> (p)
"blah"
> (p "meh")
> (p)
"meh"

Viele Funktionen (einschließlich vielen primitiven) verwenden Parameter als eine Möglichkeit, ihr Verhalten anzupassen. Zum Beispiel printf werden Sachen mit dem Port drucken, wird der Wert des current-output-port Parameter ist. Nun, sagen, dass Sie eine Funktion haben, die etwas druckt:

> (define (foo x) (printf "the value of x is ~s\n"))

Sie in der Regel diese Funktion aufrufen und etwas gedruckt auf dem Bildschirm sehen - aber in einigen Fällen möchten Sie es verwenden, um etwas in eine Datei oder was auch immer zu drucken. Sie können dies tun:

(define (bar)
  (let ([old-stdout (current-output-port)])
    (current-output-port my-own-port)
    (foo some-value)
    (current-output-port old-stdout)))

Ein Problem dabei ist, dass es mühsam zu tun ist - aber das ist leicht mit einem Makro gelöst. (In der Tat hat PLT noch ein Konstrukt, das das tut in einigen Sprachen. fluid-let) Aber es gibt mehr Probleme hier: was passiert, wenn der Anruf führt zu einem Laufzeitfehler foo? Dies könnte das System in einem schlechten Zustand verlassen, in dem alle Ausgaben zu Ihrem Hafen geht (und Sie werden nicht einmal sehen, ein Problem, da es nichts gedruckt wird). Eine Lösung für die (die fluid-let auch verwendet) ist die Speicherung / Wiederherstellung des Parameters mit dynamic-wind zu schützen, die so sicher macht, wenn ein Fehler vorliegt (und mehr, wenn Sie über Fortsetzungen wissen), dann wird der Wert noch gestellt.

Die Frage ist also, was ist der Sinn von Parametern, anstatt nur Globals und fluid-let mit? Es gibt zwei weitere Probleme, die Sie mit nur Globals nicht lösen können. Eine davon ist, was passiert, wenn Sie mehrere Threads haben - in diesem Fall, das Setzen der Wert vorübergehend andere Threads beeinflussen, die auf die Standardausgabe drucken können noch wollen. Parameter lösen dies durch pro Thread einen bestimmten Wert aufweist. Was passiert, ist, dass jeder Thread „erbt“ den Wert aus dem Thread, der es erstellt wird, und Änderungen in einem Thread sind nur sichtbar, in diesem Thread.

Das andere Problem ist subtiler. Sagen Sie, dass Sie einen Parameter mit einem numerischen Wert haben, und Sie möchten Folgendes tun:

(define (foo)
  (parameterize ([p ...whatever...])
    (foo)))

In Schema „Endaufruf“ sind wichtig - sie das grundlegende Werkzeug für die Erstellung von Schleifen sind und vieles mehr. parameterize hat einige Magie, die es den Parameterwert vorübergehend ändern kann, aber immer noch diese Endaufruf zu bewahren. Zum Beispiel in dem obigen Fall, Sie wird in eine Endlosschleife bekommen, anstatt einen Stapelüberlauf-Fehler zu bekommen - was passiert, ist, dass jeder dieser parameterize Ausdrücke irgendwie erkennen kann, wenn es eine frühere parameterize, dass keine länger braucht, um seine Bereinigung zu tun.

Schließlich parameterize tatsächlich nutzt zwei wichtige Teile der PLT seine Arbeit zu tun: es Thread-Zellen verwendet pro Thread Werte zu implementieren, und es verwendet Fortsetzung Marken der Lage sein Schwanz-Anrufe zu erhalten. Jede dieser Funktionen ist nützlich für sich.

Andere Tipps

parameterize setzt bestimmte Parameter auf bestimmte Werte für die Dauer des Blocks, ohne ihre Werte zu beeinflussen außerhalb.

parametrieren ist ein Mittel, mit dem Sie dynamisch innerhalb einer bestehenden Funktion Rebinds Werte können, ohne Lambda zu verwenden, dies zu tun. In der Praxis ist es manchmal viel einfacher parametrierbaren zu verwenden, um re-bind Werte innerhalb einer Funktion nicht erforderlich ist, Argumente zu übergeben und binden sie Lambda verwenden.

Zum Beispiel, sagen, dass eine Bibliothek, die Sie HTML zu stdout verwenden aussendet, sondern aus Gründen der Bequemlichkeit mögen Sie diesen Wert in eine Zeichenfolge zu erfassen und zu weiteren Operationen darauf ausführen. Die Bibliothek Designer hat mindestens zwei Entscheidungen, die einfach für Sie zu machen: 1) an die Funktion einen Ausgangs-Port als Argument akzeptieren oder 2) die aktuelle Ausgabe-Port-Wert parametrieren. 1 ist hässlich und ein Streit. 2 ist schöner, da die wahrscheinlichste Verhalten zu stdout drucken, aber falls Sie einen String-Anschluss drucken können Sie nur den Aufruf dieser Funktion parametrieren.

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