We were asked to write a procedure that when given a list it will replace the first occurrence of a given element and only the first, but the catch is to write in CPS style. We are unable to turn it to CPS style written procedure that is given a success-cont and fail-cont..
If anyone is willing to give it a try we will really appreciate it :]
The procedure we have (graciously provided by answers here):
(define (replace-one list old new)
(cond ((pair? list)
(let ((next (replace-one (car list) old new)))
(cons next
(if (equal? next (car list)) ; changed?
(replace-one (cdr list) old new) ; no, recurse on rest
(cdr list))))) ; yes, done
((eq? list old) new)
(else list)))
The OP asks for a transformation with two continuations - success and failure. This is easy enough to do: we start with a CPS version of deep-copy (car-cdr recursion), as usual, and then we just imagine that we have two ways to return a value: when we've just found the old value, so we return the new one instead and will stop looking any further; and if we didn't find it yet - in which case we return what we have and will keep looking for it.
this way we're practically forced to preserve the original list structure as much as possible.
Testing it with
correctly produces
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:
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: