Wolfe Macfarlane
Wolfe Macfarlane

Reputation: 139

Flexible replace substring - Scheme

Is there, in Scheme, a good way to replace a substring of a string with another string, the length of which could vary? I am looking for something similar to this:

(replace-all string pattern replacement)
(replace-all "slig slog slag" "g" "ggish")
    => "sliggish sloggish slaggish"

Upvotes: 1

Views: 1979

Answers (2)

Sylwester
Sylwester

Reputation: 48775

You can roll your own. It's not very efficient but it will do the work on small strings. (I wouldn't use it on string lengths above a million chars)

Make (prefix? src prefix) such that i evaluates to #t if the beginning of the list src is the same as prefix.

Make (append-reverse rev-head tail) such that (append-reverse '(1 2 3) '(4 5 6)) ; ==> (3 2 1 4 5 6). This could easily be done with foldl or it's a standard procedure in SRFI-1

Then (replace-all haystack needle replacement) is quite simple:

(define (replace-all haystack needle replacement)    
  ;; most of the processing works on lists 
  ;; of char, not strings.
  (let ((haystack (string->list haystack))
        (needle (string->list needle))
        (replacement (string->list replacement))
        (needle-len (string-length needle)))
    (let loop ((haystack haystack) (acc '()))
      (cond ((null? haystack)
             (list->string (reverse acc)))
            ((prefix? haystack needle)
             (loop (list-tail haystack needle-len)
                   (reverse-append replacement acc)))
            (else
             (loop (cdr haystack) (cons (car haystack) acc)))))))

(replace-all "The cat looks like a cat." "cat" "dog")
; ==> "The dog looks like a dog."

Upvotes: 4

Óscar López
Óscar López

Reputation: 236140

Sure, take a look at the documentation of your Scheme interpreter to find a suitable procedure. For instance, in Racket we have string-replace which works like this:

(string-replace "slig slog slag" "g" "ggish")
=> "sliggish sloggish slaggish"

Upvotes: 3

Related Questions