我在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函数,我会收到错误。那么有人可以帮我展示如何解决这个错误?我对递归并不是很熟悉......
先谢谢!
答案 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>)