错误:Scheme中的合同违规

时间:2013-11-27 22:27:19

标签: recursion scheme

我在Scheme中练习递归。我的代码用于获取一个模式子句和一个语句,然后在语句匹配模式时返回绑定列表,如果不是,则返回false:

(define remove-question-mark
  (lambda (s1)
    (if (memq #\? (string->list (symbol->string s1)))
        (cdr (string->list (symbol->string s1)))
        '())))

(define check-two-symbol
  (lambda (symbol1 symbol2)
    (if (and (regexp-match #rx#"\\?attrs" (symbol->string symbol1)) (list? symbol2))
        (cons symbol1 (list symbol2))
        (if (equal? symbol1 symbol2)
            '()
            (if (equal? (remove-question-mark symbol1) (string->list (symbol->string symbol2)))
                (cons symbol1 symbol2)
                #f)))))

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (null? (car state2)))
        '() 
        (list (check-two-symbol (car state1) (car state2)) (clause (cdr state1) (cdr state2))))))

这是我的意见:

(clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))

我的代码中出现此错误:

car: contract violation
  expected: pair?
  given: '()

预期产出:

((?der . der)
(?e1 . e1)
(?e2 . e2)
(?attrs_derv (prov:type "Revision")))

调试后,我发现(car state1)?attrs_derv

时发生错误

如果我像check-two-symbol那样明确地运行函数(check-two-symbol '?attrs-derv '(prov:type "Revision")),它打印得很好:

(?attrs_derv (prov:type "Revision"))

但是使用main函数,我会收到错误。那么有人可以帮我展示如何解决这个错误?我对递归并不是很熟悉......

先谢谢!

1 个答案:

答案 0 :(得分:3)

错误消息表明您正在使用不是一对的内容调用car。您只能在四个地方拨打car,因此它是clause中的一个。现在clause仅从 clause中调用,因此您无需过多地跟踪此情况。 clause应该使用哪种值?当您递归调用clause时(以下代码的最后一行),您将使用(cdr state1)(cdr state2)来调用它。有没有理由认为那些不是'()

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (car (null? state2)))
        '() 
        (list (check-two-symbol (car state1) (car state2))
              (clause (cdr state1) (cdr state2))))))
                      ------------ ------------

让我们看一下从初始输入中调用clause的内容:

(clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))
(clause '(?der ?e1 ?e2 . ?attrs_derv) '(der e1 e2 (prov:type "Revision")))
(clause '(?e1 ?e2 . ?attrs_derv) '(e1 e2 (prov:type "Revision")))
(clause '(?e2 . ?attrs_derv) '(e2 (prov:type "Revision")))
(clause '?attrs_derv '((prov:type "Revision")))

此时您将尝试在car上调用?attrs_derv,这会导致错误,因为符号不是一对。实际上,如果我们将clause简化为以下内容(以便它不会调用check-two-symbol

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (car (null? state2)))
        '() 
        (list (clause (cdr state1) (cdr state2))))))

然后尝试调用您提到的代码,我们收到错误:

> (clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))
car: contract violation
  expected: pair?
  given: '?attrs_derv

您收到其他错误的事实意味着,对check-two-symbol的调用会在某个我们看不到的地方调用car,或者您向我们展示的测试没有排队你告诉我们的输出。在任何一种情况下,看起来你都试图并行递减两个列表。如果它们都是成对的,那么你只能做到这一点,所以你可能想要像

这样的代码
(if (not (and (pair? state1) (pair? state2)))
   <then-something>
   <else-something>)