Tree 函数来检查树之间的相等性

Tree 函数来检查树之间的相等性,tree,scheme,equality,Tree,Scheme,Equality,如何在Scheme中实现一个相等函数,该函数采用两棵树并检查它们是否具有相同的元素和结构?从每棵树的根递归 如果根值相似-继续左子树,然后右子树 任何差异-从每个树的根开始递归 如果根值相似-继续左子树,然后右子树 任何差异-中断我们可以使用相等? (equal? '(a (b (c))) '(a (b (c)))) 但是,有趣的是,继Vassermans提到“休息”之后,这可能是一个利用控制权的好机会 如果我们注意到树中存在任何差异,我们可以使用call/cc发布提前回报。这样我们就可以直

如何在Scheme中实现一个相等函数,该函数采用两棵树并检查它们是否具有相同的元素和结构?

从每棵树的根递归
如果根值相似-继续左子树,然后右子树

任何差异-从每个树的根开始递归 如果根值相似-继续左子树,然后右子树

任何差异-中断

我们可以使用相等?

 (equal? '(a (b (c))) '(a (b (c))))
但是,有趣的是,继Vassermans提到“休息”之后,这可能是一个利用控制权的好机会

如果我们注意到树中存在任何差异,我们可以使用call/cc发布提前回报。这样我们就可以直接跳回调用者继续,而不必展开堆栈

这里有一个非常简单的例子。它假设树的形状良好,并且只包含树叶等符号,但它应该很有希望证明这一概念。您将看到该过程显式地接受continuation作为参数

 (define (same? a b return)
   (cond
     ((and (symbol? a) (symbol? b))      ; Both Symbols. Make sure they are the same.
       (if (not (eq? a b))
         (return #f)))
     ((and (empty? a) (empty? b)))       ; Both are empty, so far so good.
     ((not (eq? (empty? a) (empty? b)))  ; One tree is empty, must be different!
       (return #f))
     (else
       (begin
         (same? (car a) (car b) return)  ; Lets keep on looking.
         (same? (cdr a) (cdr b) return)))))
call/cc让我们捕捉当前的延续。下面是我如何称呼这个过程的:

 (call/cc (lambda (k) (same? '(a (b)) '(a (b)) k)))                      ; --> #t
 (call/cc (lambda (k) (same? '(a (b (c) (d e))) '(a (b (c) (d e))) k)))  ; --> #t
 (call/cc (lambda (k) (same? '(a (b (F) (d e))) '(a (b (c) (d e))) k)))  ; --> #f
 (call/cc (lambda (k) (same? '(a (b)) '(a (b (c) (d))) k)))              ; --> #f

我们可以使用equal?

 (equal? '(a (b (c))) '(a (b (c))))
但是,有趣的是,继Vassermans提到“休息”之后,这可能是一个利用控制权的好机会

如果我们注意到树中存在任何差异,我们可以使用call/cc发布提前回报。这样我们就可以直接跳回调用者继续,而不必展开堆栈

这里有一个非常简单的例子。它假设树的形状良好,并且只包含树叶等符号,但它应该很有希望证明这一概念。您将看到该过程显式地接受continuation作为参数

 (define (same? a b return)
   (cond
     ((and (symbol? a) (symbol? b))      ; Both Symbols. Make sure they are the same.
       (if (not (eq? a b))
         (return #f)))
     ((and (empty? a) (empty? b)))       ; Both are empty, so far so good.
     ((not (eq? (empty? a) (empty? b)))  ; One tree is empty, must be different!
       (return #f))
     (else
       (begin
         (same? (car a) (car b) return)  ; Lets keep on looking.
         (same? (cdr a) (cdr b) return)))))
call/cc让我们捕捉当前的延续。下面是我如何称呼这个过程的:

 (call/cc (lambda (k) (same? '(a (b)) '(a (b)) k)))                      ; --> #t
 (call/cc (lambda (k) (same? '(a (b (c) (d e))) '(a (b (c) (d e))) k)))  ; --> #t
 (call/cc (lambda (k) (same? '(a (b (F) (d e))) '(a (b (c) (d e))) k)))  ; --> #f
 (call/cc (lambda (k) (same? '(a (b)) '(a (b (c) (d))) k)))              ; --> #f

我也得到了一个令人失望的答案。但现在我有两个连续体,一个是真的,一个是假的。如果要在结果上进行分支,这非常有用。我还包括了“same”,它隐藏了所有的连续体,所以你不必处理它们

(define (same? a b)
  (call/cc (λ (k) (cont-same? a b (λ () (k #t)) (λ () (k #f))))))

(define (cont-same? a b return-t return-f)
  (define (atest c d)  
    ;; Are they foo?  If they both are, then true
    ;; If they both aren't false
    ;; if they are different, then we are done
    (if (and c d)
        #t
        (if (or c d)
            (return-f)
            #f)))

  (if (atest (null? a) (null? b))  ;; Are they both null, or both not null.
      (return-t)
      (if (atest (pair? a) (pair? b))
          (cont-same? (car a)
                      (car b) 
                      (λ () (cont-same? (cdr a) (cdr b) ;; If the head are the same, compare the tails
                                        return-t return-f)) ;; and if the tails are the same, then the entire thing is the same
                      return-f)          
          (if (equal? a b) ;; Both are atoms
              (return-t)
              (return-f)))))

我也得到了一个令人失望的答案。但现在我有两个连续体,一个是真的,一个是假的。如果要在结果上进行分支,这非常有用。我还包括了“same”,它隐藏了所有的连续体,所以你不必处理它们

(define (same? a b)
  (call/cc (λ (k) (cont-same? a b (λ () (k #t)) (λ () (k #f))))))

(define (cont-same? a b return-t return-f)
  (define (atest c d)  
    ;; Are they foo?  If they both are, then true
    ;; If they both aren't false
    ;; if they are different, then we are done
    (if (and c d)
        #t
        (if (or c d)
            (return-f)
            #f)))

  (if (atest (null? a) (null? b))  ;; Are they both null, or both not null.
      (return-t)
      (if (atest (pair? a) (pair? b))
          (cont-same? (car a)
                      (car b) 
                      (λ () (cont-same? (cdr a) (cdr b) ;; If the head are the same, compare the tails
                                        return-t return-f)) ;; and if the tails are the same, then the entire thing is the same
                      return-f)          
          (if (equal? a b) ;; Both are atoms
              (return-t)
              (return-f)))))

让我们考虑一下。如果我们有两棵树,每棵树都有一个元素,我们怎么知道它们是相等的呢?长度相等(因为它们由列表表示),还是用“eq”呢?也许吧?你仍然试图直接找到整个问题的解决方案。这不是正确的解决方法-你想解决尽可能小的问题,然后从中建立一个更大的解决方案。因此,如果我们有一个元素的树(它只包含根节点),而我们有另一个元素的树,我们如何检查它们是否相同?相关:。这个问题有一个特定的编程错误,但是公认的答案(免责声明:这是我的)确实包含了这个问题的答案。让我们稍微考虑一下。如果我们有两棵树,每棵树都有一个元素,我们怎么知道它们是相等的呢?长度相等(因为它们由列表表示),还是用“eq”呢?也许吧?你仍然试图直接找到整个问题的解决方案。这不是正确的解决方法-你想解决尽可能小的问题,然后从中建立一个更大的解决方案。因此,如果我们有一个元素的树(它只包含根节点),而我们有另一个元素的树,我们如何检查它们是否相同?相关:。这个问题有一个特定的编程错误,但公认的答案(免责声明:这是我的)确实包含了这个问题的答案。
call/cc
与原始问题有什么关系?看起来你只是无缘无故地想在这里使用CPS;它对实际的代码没有太大的改变。也就是说,你永远不会被退回,所以你永远不应该被退回。是的,这是免费的。那是坏形式吗?必须显式调用延续是错误的。试试看……我正试图运行它,但scheme博士抱怨ifs上缺少else条款。而且#它必须在某个时刻出现,不是吗?我也要尝试一下基于延续的搜索。嘿,Tyr,这很奇怪,我也在使用dr Scheme(没有任何问题)。如果需要,只需在else位置添加#t。“诀窍”是cond表单中的(and(empty?a)(empty?b))将隐式返回true。当给定字符串、映射、数组或其他内容时,它也将失败。我会把它留在教室里,特别是因为它是用来教书的。很好。
call/cc
和原来的问题有什么关系?看起来你只是无缘无故地想在这里使用CPS;它对实际的代码没有太大的改变。也就是说,你永远不会被退回,所以你永远不应该被退回。是的,这是免费的。那是坏形式吗?必须显式调用延续是错误的。试试看……我正试图运行它,但scheme博士抱怨ifs上缺少else条款。而且#它必须在某个时刻出现,不是吗?我也要尝试一下基于延续的搜索。嘿,Tyr,这很奇怪,我也在使用dr Scheme(没有任何问题)。如果需要,只需在else位置添加#t。“诀窍”是cond表单中的(and(empty?a)(empty?b))将隐式返回true。当给定字符串、映射、数组或其他内容时,它也将失败。我会把它留在教室里,特别是因为它是用来教书的。“好吧。”潘滕利斯你应该检查答案是否正确,这样问题就可以解决了