EDITED
A big thanks to @WillNess for pointing out and fixing a bug, lurking in the original code. Here's a corrected implementation based on his code (with stepwise derivation), commented and made idiomatic for Racket:
(define (replace-one lst a b)
(let loop ([lst lst] ; input list
[f #f] ; have we made the first replacement?
[k (lambda (ls f) ls)]) ; continue with results: list and flag
(cond
(f ; replaced already:
(k lst f)) ; continue without changing anything
((empty? lst) ; empty list case
(k lst f)) ; go on with empty lst and flag as is
((not (pair? lst)) ; - none replaced yet - is this an atom?
(if (eq? lst a) ; is this the atom being searched?
(k b #t) ; replace, continue with updated flag
(k lst f))) ; no match, continue
(else ; is this a list?
(loop (first lst) ; process the `car` of `lst`
f ; according to flag's value, and then
(lambda (x f) ; accept resulting list and flag, and
(loop (rest lst) ; process the `cdr` of `lst`
f ; according to new value of flag,
(lambda (y f) ; getting the results from that, and then
(if f ; - if replacement was made -
(k ; continuing with new list, built from
(cons x y) ; results of processing the two branches,
f) ; and with new flag, or with
(k lst f)))))))))) ; the old list if nothing was changed
Notice that a single success continuation is used (called k
in the code above) which accepts two resulting values: the list and the flag. The initial continuation just returns the final resulting list, and discards the final flag value. We could also return the flag, as indication of whether the replacement have been made at all or not. It is used internally to preserve as much of original list structure as possible, as usual with persistent data types (as seen in this answer).
Finally, always test your code:
; fixed, this wasn't working correctly
(replace-one '((((1 2) 3 4) a) 6) 'a 'b)
=> '((((1 2) 3 4) b) 6)
(replace-one '(((-))) '- '+)
=> '(((+)))
(replace-one '((-) - b) '- '+)
=> '((+) - b)
(replace-one '(+ 1 2) '+ '-)
=> '(- 1 2)
(replace-one '((+) 1 2) '+ '-)
=> '((-) 1 2)
(replace-one '(1 2 ((+)) 3 4) '+ '-)
=> '(1 2 ((-)) 3 4)
(replace-one '() '+ '-)
=> '()
(replace-one '(1 2 ((((((+ 3 (+ 4 5)))))))) '+ '-)
=> '(1 2 ((((((- 3 (+ 4 5))))))))