2013-06-09 1 views
6

Wie kann ich den Typ der Felder in dieser Struktur erzwingen?Wie erzwinge ich das Feld einer Struktur zu einem bestimmten Typ?

#lang racket 
(struct Car (model year)) 

Ich habe versucht, einen Vertrag mit (aber da ich Schläger neu bin, tut dies nicht offensichtlich ... arbeiten: P)

(provide (contract-out 
     [Car (string? integer? . -> . Car?)])) 

Beispiel: Diese succeds aber es nicht ... sollte

(define my-car (Car 2008 "A3"))

Leider ist es nicht überall geschrieben zu sein scheint, wie dies getan.

Antwort

6

Ich glaube, du mindestens ein schlagen, und vielleicht die beiden folgenden:

  1. Mit (provide (contract-out ....)) bedeutet der Vertrag gilt nur auf Modul Grenze - nur für andere Module, die require dieser ein. Wenn sich Ihr Testbeispiel also in demselben Modul befand, würde der Vertrag nicht angewendet. Stattdessen können Sie define/contract verwenden, um einen Vertrag für die Sache selbst, sowohl in dem Modul, wo es definiert ist, und außerhalb, wenn Sie provide it.

  2. Es gibt eine special form of contracts for structs, in der Sie einen Vertrag für jedes Feld angeben. Was Sie oben versucht haben, ist ein Vertrag nur für die Konstruktorfunktion. Obwohl das sein könnte, was Sie wollen, sollten Sie den Vertrag für die struct stattdessen verwenden.

Beides zu kombinieren Sie tun können:

;; Define the contract on the struct itself. 
;; Contract is used even within this module. 
(provide car) 
(define-struct/contract car ([model string?] 
          [year integer?])) 

Wenn Sie den Vertrag wollen tat nur auf Modulgrenze anzuwenden, dann würden Sie verwenden:

;; Define the contract only as `provide`d. 
;; Contract is used only for code `require`-ing this module. 
(provide (contract-out (struct car ([model string?] 
            [year integer?])))) 
(struct car (model year)) 

P. S. FWIW im Racket ist der allgemeine Stil nicht, um einen Struct-Namen zu aktivieren - car nicht Car.


aktualisieren: einfach den Unterschied deutlicher zu veranschaulichen:

#lang racket 

(module mod racket 
    (provide car0) 
    (define-struct/contract car0 ([model string?] 
           [year integer?])) 

    (car0 "foo" "bar") ;; gives contract violation 
        ;; because contract on struct itself 

    (struct car1 (model year)) 
    (provide (contract-out (struct car1 ([model string?] 
             [year integer?])))) 

    (car1 "foo" "bar") ;; does NOT give contract violation 
        ;; because contract only on the `provide` 
) 

(require 'mod) 
(car0 "foo" "bar") ;; gives contract violation 
(car1 "foo" "bar") ;; gives contract violation 
+0

BTW eine coole Sache, über Verträge ist, dass sie in einem C/C++ Sinne nicht beschränkt auf "Typen" sind. Wenn zum Beispiel das Automobil 1769 erfunden wurde, dann könnte Ihr Vertrag für "Jahr" '(und/c Ganzzahl? (>/C 1768))' anstelle von nur 'Ganzzahl? 'Sein. ;) –

+0

Vielen Dank, es hat perfekt funktioniert :) – TesX