Kiley
Kiley

Reputation: 39

Racket/Scheme - Replacing an element in a list based on a location

I was trying to define a replace procedure that basically does the same thing as the list-set. This is my code so far:

(define replace
  (lambda (s pos lst fin-lst)
    (cond
      ((zero? pos) (cons (cons (reverse fin-lst) s) (rest lst)))
      (else (replace s (- pos 1) (rest lst) (cons (first lst) fin-lst))))))

It sort of does what it's supposed to but I'm struggling to have the output look the way I want it to. For example this is the result I want

(replace 'a 2 '(1 2 3 4 5) '()) => '(1 2 a 4 5)

But as of now, this is what my procedure returns

'(((1 2) . a) 4 5)

I understand this is due to the cons vs. append, but how can I change my code to get rid of the extra parentheses and . ?

Upvotes: 1

Views: 442

Answers (2)

alinsoar
alinsoar

Reputation: 15793

try this:

(define replace
  (lambda (l pos e)
    ((lambda (s) (s s l pos (lambda(x) x)))
     (lambda (s l i col)
       (if (null? l)
           (col '())
           (if (zero? i)
               (col (cons e (cdr l)))
               (s s (cdr l) (- i 1)
                  (lambda (r)
                    (col (cons (car l) r))))))))))


(replace '(a b c d e f) 2 'x)
(replace '(a b c d e f) 0 'x)
(replace '(a b c d e f) 20 'x)

Upvotes: 0

Óscar López
Óscar López

Reputation: 236004

You almost had it! The reverse call is misplaced, and you need to use append to stick the two lists together. This is what I mean:

(define replace
  (lambda (s pos lst fin-lst)
    (cond
      ((zero? pos)
       (append (reverse (cons s fin-lst)) (rest lst)))
      (else
       (replace s (- pos 1) (rest lst) (cons (first lst) fin-lst))))))

It works as you expected:

(replace 'a 2 '(1 2 3 4 5) '())
=> '(1 2 a 4 5)

Upvotes: 1

Related Questions