[racket] multi-replace function

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Dec 7 02:15:42 EST 2010

15 minutes ago, YC wrote:
> 
> On Mon, Dec 6, 2010 at 10:21 PM, prad <prad at towardsfreedom.com> wrote:
> 
>     i'm trying create a multi-replace function in racket where you can
>     substitute for patterns in a string with items in a list:
> 
>     (mult-repl "~A"
>               "this ~A string will experience ~A substitution"
>               (list "wonderful" "massive"))
>     -> "this wonderful string will experience massive substitution"
> 
> Since it looks like what you are doing is just positional (instead of named)
> substitutions, format is good enough for the purpose: [...]

If you still want to go with the regexp approach, then note that you
can give `regexp-replace*' a function that produces the string to
return:

  (regexp-replace* #rx"~a" "foo ~a bar ~a baz ~a"
                   (lambda (_) "X"))

and you can combine this with a generator to use a different string
for each replacement:

  (define get-string
    (let ([strings '("X" "Y" "Z")])
      (lambda (_) (begin0 (car strings) (set! strings (cdr strings))))))
  (regexp-replace* #rx"~a" "foo ~a bar ~a baz ~a"
                   get-string)

or use `racket/generator' for a more generic solution:

  (require racket/generator)
  (define get-string (generator () (for-each yield '("X" "Y" "Z"))))
  (regexp-replace* #rx"~a" "foo ~a bar ~a baz ~a"
                   (lambda (_) (get-string)))


> Speed is not the most important criteria in programming these days,
> as long as it's perceived to be fast enough.  Often times, a
> performant system automatically emerges with good design.  And even
> if it needs some tuning, a well designed system is more easily
> profiled and improved.  And over time, obscurely written code will
> be hard to understand if you ever come back to it months or years
> later, so it is very important to write legible and understandable
> code.  Good design and understandable code will pay dividends even
> if it might not be the fastest code.

One thing to keep in mind is that if you only care about replacing
occurrences in some input file, then you can avoid the overhead of
collecting the full text in memory.  For example, this will read the
standard input, and replace each "~a" with a string from the list,
spitting out the new text:

  #lang racket/base
  (require racket/generator)
  (define get-string (generator () (for-each yield '("X" "Y" "Z"))))
  (define (replace-all)
    (when (regexp-match "~a" (current-input-port) 0 #f (current-output-port))
      (display (get-string))
      (replace-all)))
  (replace-all)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the users mailing list.