Racket Vertrag

Das zweite Formular mit Dem Vertrag muss in der Ausdrucksposition angezeigt werden. Der Ausdruck des endgültigen Textes sollte die gleiche Anzahl von Werten zurückgeben wie die Anzahl der in der Ergebnisspezifikation aufgeführten Kontrakte, und jeder zurückgegebene Wert wird mit seinem jeweiligen Vertrag vertraglich gebunden. Die Abfolge der Körperformen wird wie für let behandelt. Verwenden Sie einen beliebigen/c-Ergebnisvertrag, wenn es besonders wichtig ist, ein einzelnes Ergebnis aus einer Funktion zu versprechen. Verwenden Sie alle, wenn Sie so wenig wie möglich versprechen möchten (und so wenig Überprüfung wie möglich) für das Ergebnis einer Funktion. Wenn Sie an mathematische Funktionen gewöhnt sind, sollten Sie es vorziehen, dass ein Vertragspfeil zwischen der Domäne und dem Bereich einer Funktion angezeigt wird, nicht am Anfang. Wenn Sie How to Design Programs gelesen haben, haben Sie dies schon oft gesehen. In der Tat haben Sie Verträge wie diese im Code anderer Personen gesehen: Ein Modul-Grenzvertrag muss nicht in dem Modul leben, in dem die Funktion definiert ist. Hierwird die übliche /Funktion von br mit einem restriktiveren Vertrag wieder exportiert: Flachverträge können sofort vollständig auf einen bestimmten Wert überprüft werden.

Diese Art von Verträgen sind im Wesentlichen Prädikatsfunktionen. Mit Flat-Contract-Prädikat können Sie das Prädikat aus einem beliebigen Flat-Contract extrahieren; einige flache Verträge können wie Funktionen angewendet werden, in diesem Fall akzeptieren sie ein einziges Argument und geben #t oder #f, um anzugeben, ob der angegebene Wert vom Vertrag akzeptiert würde. Alle flachen Verträge, die von Funktionen in dieser Bibliothek zurückgegeben werden, können direkt als Prädikate verwendet werden, aber gewöhnliche Racket-Werte, die sich als flache Verträge verdoppeln (z. B. Zahlen oder Symbole), können dies nicht. Wenn ein Kundenmodul eine Einzahlung auf “Millionen” anwenden würde, würde es den Vertrag verletzen. Das Vertragsüberwachungssystem würde diesen Verstoß auffangen und dem Kunden vorwerfen, den Vertrag mit dem oben genannten Modul gebrochen zu haben. Im Gegensatz dazu würde das Vertragsüberwachungssystem dem Servermodul die Schuld geben, wenn die Balance-Funktion “broke” zurückgeben würde. Wenn die Funktion optionale Argumente hat, verwenden Sie den Kombinator ->*. Die obligatorischen und optionalen Argumente werden in ihre eigenen Klammern-Unterlisten gruppiert. Eine Funktion mit zwei obligatorischen Zeichenfolgenargumenten und einem optionalen Ganzzahlargument hätte also diesen Vertrag: (contract-out unprotected-submodule contract-out-item …) A -> für sich genommen ist kein Vertrag; es handelt sich um einen Vertragskombinator, der andere Verträge zu einem Vertrag zusammenfasst. Imitator-Verträge können Werte umschließen und keine Garantien bieten.

Identitätswechsel können Eigenschaften von Werten verbergen oder sogar völlig undurchsichtig machen (z. B. new-/c). Für Listen und Vektoren bietet die Vertragsbibliothek Listund und Vektor von an, die die Member dieser Strukturen überprüfen: Nur die Verwendung der vertraglich vereinbarten Variablen außerhalb des Moduls wird geprüft. Innerhalb des Moduls findet keine Vertragsüberprüfung statt. Selbstverständlich können Sie Ihre eigenen vertragsumschließenden Funktionen mit Kombinatorwie und/c mischen. Hier ist ein Modul zum Erstellen von Zeichenfolgen aus Bankdatensätzen: Dieses Modul definiert einen Betrag? und verwendet sie als Vertrag innerhalb von -> Verträgen. Wenn ein Kunde die Einzahlungsfunktion als mit dem Vertrag exportiert (-> Betrag? any) aufruft, muss er eine exakte, nicht negative ganze Zahl angeben, sonst der Betrag? Auf das Argument angewendete Funktion wird #f zurückgeben, wodurch das Vertragsüberwachungssystem dem Client die Schuld gibt. Ebenso muss das Servermodul eine exakte, nicht negative Ganzzahl als Ergebnis des Gleichgewichts bereitstellen, um tadellos zu bleiben. In einigen Situationen kann eine Funktion geschrieben werden, um einen laxeren Satz von Eingaben zu akzeptieren, wenn sie von anderem Code im selben Modul aufgerufen werden.

Für solche Anwendungsfälle ist die durch Definition/Vertrag festgelegte Vertragsgrenze zu streng. Beachten Sie, dass contract-out keine Strukturinstanzen schützt, die über deserialize erstellt werden, wenn die Struktur mit serialisable-struct oder define-serialisable-struct erstellt wird.