如何在 Scheme 中检查两个 S 表达式在结构上是否相同?

How to check whether two S-expressions are structurally identical in Scheme?

我不太确定如何处理这个问题。我想我想用一个辅助函数分别遍历 x 和 y,并让那个辅助函数 return 一个值取决于它找到什么,然后在(结构上? 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

我想我明白为什么你给出的例子是真假,但我不确定结果表达式树是什么样的。假设您有表达式 e,例如数学表达式 (+ (+ 2 4) 5)。根 +(car e),左树 (+ 2 4)(cadr e),右树 5(caddr e)。在结构上,该表达式与 (+ (- 3 7) 1) 相同,但计算结果不同...

如果您导航表达式但没有 c(a)drc(a)ddr,则您已到达该方向的遍历终点。

您可能需要一个辅助方法,但我想 (and (equal? (car x) (car y)) (structurally? (cdr x) (cdr y)) (structurally? (cddr x) (cddr y))) 的效果会让您入门。

为此,我们必须同时遍历两个列表列表,特别注意边缘情况。如果我们设法遍历列表而其中一个列表没有在另一个列表之前结束,那么我们可以说它们在结构上是相等的。试试这个:

(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

Óscar Ló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 不是一对,则表达式在结构上不等价。这是递归的另一个最终情况。

最终,递归情况等于另一种解法。