[racket] Splicing format string?

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Thu Sep 1 10:31:54 EDT 2011

J. Ian Johnson wrote at 09/01/2011 09:43 AM:
> I have a list of symbols '(a b c) that I want to be printed "a b c" as part of string I'm formatting.

If you don't mind parentheses, you can do: (format "~s" syms)

I think that "format" has conspicuously avoided getting like C "printf" 
or the super-scary CL function.  It's convenient for what it is, and is 
not intended to be anything more than what it is.

I think there are some formatting libraries in PLaneT.

One thing to keep in mind as you're formatting things: if you want to do 
be formatting huge outputs, you'll want to be writing incrementally to a 
port, not making a massive string.  Below is a little code I just banged 
out to illustrate writing formatting code that scales.  It's not 
intended to be a gee-whiz demo.  ("You have to write all that code just 
to put spaces in a list?!")

#lang racket

;; Sometimes it's preferable to write formatting procedures that first
;; write to ports rather than generate strings...

(define (display-list-items/separator lst
                                      (out (current-output-port)))
  (or (null? lst)
      (let loop ((item (car lst))
                 (lst  (cdr lst)))
        (write item out)
        (if (null? lst)

            (begin (display separator out)
                   (loop (car lst) (cdr lst)))))))

;; Then you can combine it with other output procedures, and it scales
;; to arbitrary size of output...

(define (write-report lst out)
  ;; TODO: Write a gigabyte of earlier report text here.
  (display "This is my list: {" out)
  (display-list-items/separator lst ", " out)
  (display "}\n" out)
  ;; TODO: Write some more report text here.

;; For dealing with small outputs, you can make a wrapper for the
;; writing procedure that returns a string...

(define (list-items->string/separator lst separator)
   (lambda (out)
     (display-list-items/separator lst separator out))))

;; Obligatory tests...

(require (planet neil/overeasy:1:0))

 (test (format "~a" (string-join (map symbol->string '(a b c)) " "))
       "a b c")

 (test (list-items->string/separator '(a b c) " ")
       "a b c")

 (test (list-items->string/separator '(a b c) ", ")
       "a, b, c")

 (test (list-items->string/separator '() " ")


Posted on the users mailing list.