ads27
ads27

Reputation: 71

scheme replace a1 in a list of lists with a2, both a1 a2 is flat

Going further for the scheme how do you sum numbers in a list when you have structures and list of lists now i want to replace all occurrences of atom a1 in SEXP with atom a2.

For example,

(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)

My code,

;; 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)))])])) 

for the part to determine if it is a1, do we need call a helper function we could do so in my way present here?

Also, since sexp is a list of lists and atom is flat,

 (symbol=?  (first sexp) a1) 

might cause problem since scheme would expect a symbol but given (list xxxxxx)

How do you fix that problem as well?

Upvotes: 0

Views: 134

Answers (1)

Óscar López
Óscar López

Reputation: 236004

The code can be simplified a great deal if we make sure that the equality comparison is performed only when we're sure that sexp is an atom, try this:

(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]))

The same comments to your previous question apply, though: you must be consistent, and if you're using SEXP structs then you must stick to using that struct's accessor procedures, instead of first, rest, etc. Also notice how we can use equal? for comparisons when we don't know beforehand the specific type of the elements. Test it like this, and notice the correct order of the parameters:

(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))

Upvotes: 1

Related Questions