[racket] regexp-replace* with input-port ==> Re: multi-replace function

From: YC (yinso.chen at gmail.com)
Date: Tue Dec 7 05:24:47 EST 2010

On Tue, Dec 7, 2010 at 12:25 AM, Eli Barzilay <eli at barzilay.org> wrote:
>
> Actually, there's a problem -- there is already an optional argument
> for the prefix, and if an output port is added, it should be added
> before that for consistency but that will be incompatible.


That's unfortunate.  Looking at v4.2.5 I did not see the input-prefix param,
so that's probably added in v5.0.  I guess it's either be a new name
(something like regexp-replace*/out and regexp-replace/out) or added after
the prefix.

I did a quick proof of concept against 4.2.5 (which doesn't have the
inconsistency of input-prefix), and it works AFAICT.  Of course it's better
if this is implemented in the same layer as other regexp functions.

(define (insert-spec->callback spec)
  (define (make-substitution matched)
    (lambda (m . rest)
      (cond ((bytes=? m #"\\&") #"&")
            ((bytes=? m #"\\\\") #"\\")
            ((bytes=? m #"&") (car matched))
            ((= 2 (length rest))
             (list-ref matched (string->number (bytes->string/utf-8 (cadr
rest)))))
            (else #""))))
  (lambda (matched . parts)
    (regexp-replace* (byte-pregexp #"(\\&|\\\\([0-9]+))")
                     spec
                     (make-substitution (cons matched parts)))))

(define (regexp-replace*/out pat in insert (out #f)) ;; what does #f mean?
  (define (helper insert)
    (let loop ((matched (regexp-match pat in 0 #f out)))
      (unless (not matched)
        (display (apply insert matched) out)
        (loop (regexp-match pat in 0 #f out)))))
    (if (input-port? in)
        (if (output-port? out)
            (helper (if (procedure? insert)
                        insert
                        (insert-spec->callback insert)))
            (regexp-replace* pat (port->bytes in) insert))
        (regexp-replace* pat in insert)))

(define (regexp-replace/out pat in insert (out #f))
  (define (helper insert)
    (let ((matched (regexp-match pat in 0 #f out)))
      (unless (not matched)
        (display (apply insert matched) out)
        (copy-port in out))))
  (if (input-port? in)
      (if (output-port? out)
          (helper (if (procedure? insert)
                      insert
                      (insert-spec->callback insert)))
          (regexp-replace pat (port->bytes in) insert))
      (regexp-replace pat in insert)))

> (regexp-replace*/out #px"[0-9]+" (open-input-string "1929,1939,1949,1959")
"+\\0" (current-output-port))
+1929,+1939,+1949,+1959


Cheers,
yc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20101207/1d355f68/attachment.html>

Posted on the users mailing list.