scheme用a2替换列表中的a1,a1 a2都是平的

时间:2014-11-05 19:04:31

标签: scheme racket

进一步研究scheme how do you sum numbers in a list when you have structures and list of lists现在我想用SE1P替换所有出现的原子a1和原子a2。

例如,

(replace (list (list 'a 'b) (list 1 3 )) 'a 'b) =>
(list (list 'b 'b) (list 1 3))

(replace (list (list 'a 'b) (list 1 3)) 1 2) =>
(list (list 'a 'b) (list 2 3))

;; An ATOM is one of: 
;; -- Symbol
;; -- String 
;; -- Number

(define-struct SEXP (ATOM SEXP))

;; An SEXP (S-expression) is one of: 
;; -- empty 
;; -- (cons ATOM SEXP)
;; -- (cons SEXP SEXP)

我的代码,

;; replace: Atom atom sexp -> sexp

(define (replace a1 a2 sexp)
   (cond
      [(empty? sexp) empty]
      [(SEXP? sexp)
             (cons (replace a1 a2 (first sexp)) (replace a1 a2 (rest sexp)))]
      [else
         (cond 
             [(or (symbol=?  (first sexp) a1)
                  (string=?  (first sexp) a1)
                  (=  (first sexp)  a1))
              (cons a2 (replace a1 a2 (rest sexp)))]
             [else (cons (first sexp) (replace a1 a2 (rest sexp)))])])) 

对于确定它是否为a1的部分,我们是否需要调用辅助函数,我们可以按照我在这里出现的方式执行此操作?

另外,由于sexp是列表和原子是平的,

 (symbol=?  (first sexp) a1) 

可能会导致问题,因为scheme会期望一个符号但是给出(list xxxxxx)

你如何解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

如果我们确保只有当我们确定sexp是一个原子时才执行相等比较,那么代码可以简化很多,试试这个:

(define (replace a1 a2 sexp)
  (cond
    [(empty? sexp) empty]
    [(SEXP? sexp) ; (define SEXP? pair?)
     (cons (replace a1 a2 (first sexp))
           (replace a1 a2 (rest  sexp)))]
    [(equal? sexp a1) a2]
    [else sexp]))

同样适用于您之前问题的评论:您必须保持一致,如果您使用的是SEXP结构,那么您必须坚持使用该结构的访问程序,而不是firstrest等。当我们事先不知道元素的具体类型时,还要注意我们如何使用equal?进行比较。像这样测试一下,注意参数的正确顺序:

(replace 'a 'b (list (list 'a 'b) (list 1 3)))
=> '((b b) (1 3))

(replace 1 2 (list (list 'a 'b) (list 1 3)))
=> '((a b) (2 3))