[plt-scheme] Newbie macro problem

From: Erich Rast (Erich.Rast at t-online.de)
Date: Fri Nov 1 11:57:53 EST 2002


I need a replacement for format that behaves exactly like format except 
that it takes an arbitrary number of arguments and simply ignores any 
more arguments than the format string requires:

(flex-format "hello ~a" 'world) ==> "hello world"
(flex-format "hello ~a" 'world 'folks 'good-day) ==> "hello world"

Looks simple, and I've defined a function count-format-arguments that 
returns the number of format-tags that require an argument. If I have a 
function defined as (flex-format str . rest)

(sublist rest 0 (count-format-arguments str))

yields a list of the arguments that are really required by str, 
ommiting any further arguments.

However, I simply can't figure out how to actually define flex-format. 
I'v tried various functions and macros for hours and never got the 
right result. Using apply and quasi-quotes, I either got errors about a 
missing syntax-transformer, or I didn't get the quasi-quotation right.

Could someone show me how to define flex-format or explain a similar 
example to me?

Best regards,


  (define (count-format-arguments str)
     (let loop ((li (string->list str))
                (elem #f)
                (c 0))
       (cond ((null? li) c)
             ((not elem) (loop (cdr li) (car li) c))
             ((equal? elem #\~) (case (car li)
                                  ((#\a #\A #\v #\V #\s #\S #\e #\E  #\c 
#\C #\b #\B #\o #\O #\x #\X)
                                   (loop (cdr li) (car li) (+ c 1)))
                                  (else (loop (cdr li) (car li) c))))
             (else (loop (cdr li) (car li) c)))))

; grabbed from the Net:
(define sublist
     (lambda (ls m n)
       (define (sublist-internal result ls m n)
         (cond ((or (= m n) (= n 0)) ; limit cases
               ((null? ls)
                ;; either complain or return a useful default
               ((= m 0)
                (sublist-internal (cons (car ls) result) (cdr ls) 0 (- n 
               (else (sublist-internal result (cdr ls) (- m 1) (- n 
       (reverse! (sublist-internal '() ls m n))))

Posted on the users mailing list.