我正在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 '?attrs-derv '(prov:type "Revision"))
一样单独运行函数check-two-symbol
,它会很好地打印出来:
(?attrs_derv (prov:type "Revision"))
但是对于主函数,我会出错。那么,有人能帮我展示如何修复这个错误吗??我对递归不是很熟悉。。。。
提前感谢!
错误消息指示您正在使用非配对的东西调用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")))
此时,您将尝试在?attrs_derv
上调用car
,这将导致错误,因为符号不是一对。事实上,如果我们将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>)