进一步研究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)
你如何解决这个问题呢?
答案 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
结构,那么您必须坚持使用该结构的访问程序,而不是first
, rest
等。当我们事先不知道元素的具体类型时,还要注意我们如何使用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))