我试图为我的二叉树结构建立递归合同:
(struct node (l r))
(struct leaf (val))
(define (tree-of val)
(or/c (struct/c leaf val) (struct/c node (tree-of val) (tree-of val))))
(define/contract (id-tree t)
(-> (tree-of symbol?) (tree-of symbol?))
t)
(id-tree (leaf 'a))
尽管我的合同似乎导致了无限循环,但不确定为什么。首先,它是否应该在or / c收到任何正值(在这种情况下来自(struct / c leaf val))之后停止? 即使它检查第二个谓词,(叶'a)显然也不是节点,那么为什么还要递归调用树形树呢?
答案 0 :(得分:2)
从某种意义上讲,有两个阶段:合同计算和合同检查。您的示例不会在合同计算阶段终止。
假设您将(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)))