В некотором смысле, есть две фазы: вычисление контракта и проверка контракта. Ваш пример не заканчивается в фазе вычисления контракта.
Предположим, вы добавили (or/c <a> <b>)
к значению x
. or/c
- это просто нормальная функция, поэтому при вызове по значению (что и есть у Racket) будут вычислены и <a>
, и <b>
.
Если ничего не происходит не так, <a>
и <b>
должны оценить значения контракта va
и vb
соответственно. Затем проверка контракта начинается с проверки x
против va
. Если это не удается, тогда он проверяет x
против vb
.
Проблема с вашим примером заключается в том, что процесс вычисления значений контракта даже не прекращается. На тот момент проверки еще не проводились.
Чтобы выполнить то, что вы хотите сделать, используйте flat-rec-contract
:
(define (tree-of/c val)
(flat-rec-contract tree-of
(struct/c leaf val)
(struct/c node tree-of tree-of)))