Существует как минимум 3 способа:
Определить структуру с контрактом, используя define-struct/contract
.
Определите структуру с охраной, используя struct
с #:guard
.
a) Охрана, которая использует контракт с struct-guard/c
.
b) Защита, определенная вручную с помощью unless
, boolean?
, raise-argument-error
.
Напишите вашу программу в Типизированная ракетка вместоРакетка, и используйте такой тип, как Boolean
.
1: Структура с контрактом
Вы можете использовать define-struct/contract
следующим образом:
(define-struct/contract mystruct ([val boolean?]))
Правильно и неправильно его использовать:
> (define xt (mystruct #true))
> (define xf (mystruct #false))
> (mystruct-val xt)
#true
> (mystruct-val xf)
#false
> (mystruct 3)
make-mystruct: contract violation
expected: boolean?
given: 3
in: the 1st argument of
(-> boolean? symbol? any)
contract from: (struct mystruct)
blaming: .../so-54901923.rkt
(assuming the contract is correct)
2: построить с защитой
Вы можете использовать ключевое слово #:guard
из struct
как это:
(struct mystruct [val]
#:guard <guard-procedure>)
Самый простой способ определить защитную процедуру - это использовать библиотечную функцию, например struct-guard/c
на снимке Racket HEAD (не в 7.2, будет выпущен в следующей версии Racket).
(struct mystruct [val]
#:guard (struct-guard/c boolean?))
Использование, правильное и правильноеctly:
> (define xt (mystruct #true))
> (define xf (mystruct #false))
> (mystruct-val xt)
#true
> (mystruct-val xf)
#false
> (mystruct 3)
mystruct: contract violation
expected: boolean?
given: 3
in: boolean?
contract from:
.../so-54901923.rkt
blaming: .../so-54901923.rkt
(assuming the contract is correct)
Если вам недоступно что-то вроде struct-guard/c
или если вам нужно больше мощности / контроля, чем обеспечивает struct-guard/c
, вы можетеопределить защитную процедуру вручную.Если структура имеет n полей, сторожевая процедура должна принимать n + 1 аргументов, соответствующих полям плюс имя структуры.
Например, для вашегоmystruct
, это должна быть функция, которая принимает значение поля val
и имя:
(lambda (val name)
???)
Защитная процедура должна возвращать результат с несколькими значениями, используя n значения, соответствующие полям.
(lambda (val name)
(values val))
И он может запускать произвольные проверки значений перед их передачей:
(lambda (val name)
(unless (boolean? val)
(raise-argument-error name "boolean" val))
(values val))
Помещая его как #:guard
:
(struct mystruct [val]
#:guard (lambda (val name)
(unless (boolean? val)
(raise-argument-error name "boolean" val))
(values val)))
Использование:
> (define xt (mystruct #true))
> (define xf (mystruct #false))
> (mystruct-val xt)
#true
> (mystruct-val xf)
#false
> (mystruct 3)
mystruct: contract violation
expected: boolean
given: 3
3: набранная ракетка
Можно использовать #lang typed/racket
.Его struct
форма имеет тип для каждого поля:
#lang typed/racket
(struct mystruct ([val : Boolean]))
Используя его:
> (define xt (mystruct #true))
> (define xf (mystruct #false))
> (mystruct-val xt)
- : Boolean
#true
> (mystruct-val xf)
- : Boolean
#false
> (mystruct 3)
Type Checker: type mismatch
expected: Boolean
given: Positive-Byte in: 3