我不完全确定如何处理这个问题。我想我想通过辅助函数分别通过x和y,并让辅助函数根据它找到的函数返回一个值,然后比较它们(结构上?x y)。但是,我可以想到使用这种方法的多种方法可能会出错。
define (structurally? x y)
(
...
)
示例:
(structurally? quote(1 2 (3 a 5) (b 6 c "string" 7 (5)) 9)
quote(2 1 (3 "string" 5) (b 6 c a 7 (5)) 9))
结果是#t
(structurally? '(1 2 (3 a b 5) (b 6 c "string" 7 (5)) 9)
'(2 1 (3 "string" 5) (b 6 c d a 7 (5)) 9))
结果是#f
答案 0 :(得分:1)
为此,我们必须同时遍历两个列表列表,特别注意边缘情况。如果我们设法遍历列表而没有其中一个在另一个之前结束,那么我们可以说它们在结构上相等。试试这个:
(define (structurally? exp1 exp2)
; if we reach the end of both lists, they're equal
(cond ((and (null? exp1) (null? exp2)) #t)
; if we reach the end of one before the other, they're distinct
((and (null? exp1) (not (null? exp2))) #f)
; if we reach the end of one before the other, they're distinct
((and (not (null? exp1)) (null? exp2)) #f)
; if we find an atom they're equal, no matter its value
((not (pair? exp1)) #t)
; recursive step: advance over `car` and `cdr` of both lists
; simultaneously, combining all partial results using `and`
(else
(and (structurally? (car exp1) (car exp2))
(structurally? (cdr exp1) (cdr exp2))))))
按预期工作:
(structurally? '(1 2 (3 a 5) (b 6 c "string" 7 (5)) 9)
'(2 1 (3 "string" 5) (b 6 c a 7 (5)) 9))
=> #t
(structurally? '(1 2 (3 a b 5) (b 6 c "string" 7 (5)) 9)
'(2 1 (3 "string" 5) (b 6 c d a 7 (5)) 9))
=> #f
答案 1 :(得分:1)
ÓscarLópez的解决方案可以通过这种方式简化:
(define (structurally? exp1 exp2)
(cond ((not (pair? exp1)) (not (pair? exp2)))
((not (pair? exp2)) #f)
(else (and (structurally? (car exp1) (car exp2))
(structurally? (cdr exp1) (cdr exp2))))))
在cond
的第一个分支中,我们说如果第一个表达式不是一对,那么函数的结果就是检查第二个表达式是否也不是一对。这也是递归的最后一种情况之一,因为你不能重复使用非配对值。
在第二个分支中,我们知道exp1
是一对,所以如果exp2
不是一对,则表达式在结构上不等同。这是递归的另一个最后一例。
最后,递归情况等于另一种解决方案。
答案 2 :(得分:0)
我想我明白为什么你给出的例子是真的和假的,但我不确定结果表达式树的样子。假设您有表达式e
,例如数学表达式(+ (+ 2 4) 5)
。根+
为(car e)
,左侧树(+ 2 4)
为(cadr e)
,右侧树5
为(caddr e)
。在结构上,该表达式与(+ (- 3 7) 1)
相同,但评估结果不同......
如果您浏览表达式并且没有c(a)dr
或c(a)ddr
,那么您已经到达了该方向的遍历结束。
你可能需要一个辅助方法,但我想象(and (equal? (car x) (car y)) (structurally? (cdr x) (cdr y)) (structurally? (cddr x) (cddr y)))
的效果会让你开始。