So <format> is a function that can take a control
string, or a function generated by the macro
<formatter>. Said function contains an
(apply #'format (args) ...). So where's the gain
in efficiency? Is it that the function somehow
eliminates <format>'s need to parse the control string
at run time, i.e. moving something messy up to compile
time?
When and how would this be used to advantage?
Maybe with very complex control strings or if
the <format> is embedded in some iterative structure.
But it doesn't seem to be used routinely.
Carl Taylor
FORMATTER allows you to compile the format control
string into code and thus removes the runtime interpretation
aspect of it.
BUT. I can't remember if any CL implementation actually implements
a FORMAT compiler. Last I've looked, most just call FORMAT as usual.
FORMATTER is defined just in case some implementation
wants to provide that functionality.
> I'm trying to get a grip on <formatter>.
>
> So <format> is a function that can take a control
> string, or a function generated by the macro
> <formatter>. Said function contains an
> (apply #'format (args) ...). So where's the gain
> in efficiency?
Said function has *behavior equivalent to* the (apply #'format ...)
example in the spec. However, that's just a guarantee that nothing
FORMATTER does will break the semantics you expect from FORMAT. It's
possible, though, for FORMATTER to do something to produce more
efficient code.
> Is it that the function somehow eliminates <format>'s need to parse
> the control string at run time, i.e. moving something messy up to
> compile time?
That's my understanding.
> When and how would this be used to advantage?
> Maybe with very complex control strings or if
> the <format> is embedded in some iterative structure.
>
> But it doesn't seem to be used routinely.
When I first learned about FORMATTER, I thought I'd use it a lot. It
turns out that my favorite Lisp (SBCL) already does it for me if the
control string is a literal string. I never bother to save away a
FORMATTER function and re-use it.
The easiest way I've found to make FORMAT go real fast is to set
*PRINT-PRETTY* to NIL.
Zach
Allegro does, and apparently so does SBCL.
As has been pointed out, it isn't necessary that formatter turn the
format control string into "code", whatever that means, but only that a
function be returned that is more efficient presumably by preprocessing
the format control.
In Allegro formatter returns a function, as required, but since the
translation of a format control string into a function often produces
a rather large function, the formatter function is a closure capturing
an intermediate representation that achieves most of the speed
optimization without incurring the huge code space overhead.
The ANS doesn't point this out, but it should be obvious that calls to
format with a constant format control string can have the work done by
formatter performed by a compiler macro on format. On the other hand,
most programs contain lots of format control strings that are used only
in rare conditions, so it is a little wasteful of space to transform
unconditionally at compile time. The behavior in Allegro under default
optimization is to transform into a lazy conversion of the format
control. A format control string in a function is translated and
cached by the function the first time it is used.
These optimizations were implemented perhaps 16 years ago, when memory
was measured in MB rather than GB. But instruction caches are still
measured in MB...
Thanks for the update.
Maybe somebody with more FORMAT-fu may want to play with this idea:
Replace Lisp with FORMAT strings as a surface syntax in the REPL.
Enter
(defun format-repl ()
(loop
do (terpri)
do (princ "format > ")
do (format t (read-line))))
? (format-repl)
format > ~%12~%34
12
34
format >
How would you compute FAK, FIB, ACKERMANN, etc.?
That makes a lot of sense. If I wanted to speed up format,
that's what I would do.
History/brag: I was the one who put "format" into Lisp. It
was a direct ripoff of Multics's ioa_. (This predates
Unix printf.)