[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Format strings are wrong

On Fri, Dec 26, 2003 at 07:35:41PM +0100, Paul Schlie wrote:

> Gentlemen, with all due respect, and understanding that the following
> thoughts may be best expressed in an alternative SRFI; but Upon reviewing
> the discussion archive, I feel compelled to voice support of Marc's
> opinions; as I don't believe  C'ish embedded numerical format string hacks
> actually materially help porting code, or are particularly favored by folks
> who are familiar with C; but actually reduce the potential simplicity and
> efficiency of mixed text/numerical string formatting which the language
> could and arguably should otherwise encourage.

The SRFI process isn't just about porting, but also standardizing
libraries.  One of the primary motivations of SRFI-1 was that all
Schemes provided varying levels of add-on list utilities with
incompatible API's.  In this case almost all Schemes at least support
SRFI-28, and many support some or all of the full Common-Lisp format,
so it is definitely something people find useful and should be
standardized.  Many people feel SRFI-48 doesn't go far enough, so
there will likely be at least one more format SRFI.  Perhaps that will
explicitly make the individual formatting procedures accessible as
they are in Dirk Lutzebaeck's implementation, which would give you the
option of using both styles.

> Possibly something along the lines of simply adopting the notion that:
> (str-fmt ....) [or (string ...) be extended] to accept mixed string, symbol,
> character and numerical arguments, and produces a string resulting from the
> concatenation of its argument's string equivalences

Probably best not to overload string, especially in light of recent
discussions as to just what a character is.  Also, the procedure
should definitely output to a port, not a string.  But even using a
port this becomes inefficient if you inline write's:

  (define (write-to-string x) (with-output-to-string (cut write x)))
  (fmt #t "list: " (write-to-string ls) #\newline)

and likewise for performing different number->string conversions in
the middle of a format.  You really have to break it apart as:

  (display "list: ")
  (write ls)

which when compared with

  (format #t "list: ~S\n" ls)

looks clumsy and verbose, especially when you have many of these
throughout a program almost tripling the number of lines, and
especially when you have to wrap them in begins.  Format is very
concise and not only lets you re-use the format string in parts of
your program, it lets you easily change it at runtime (even in an
eval-less Scheme) and lets you load it from things like config files.
Consider the log files of a server that need to produce customizable
output, like this from my httpd.conf:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %T %v" full

Or consider the Emacs mode-line-format string which lets you customize
(again at runtime) what appears in your mode-line.  Of course, Emacs
allows nested lists as the format, which may be a consideration for
future format SRFIs rather than consider introducing artificial
nesting with ~<...~> etc.

By keeping the logic in one place format is also much better suited to
things like i18n, and can provide more efficient control over
columnating and padding.

All around, format is more consice, more efficient, and more flexible
than the alternatives.  That doesn't mean we couldn't use some more
functional interfaces, but they will likely not replace format.