Re: FORMAT ~<...~:@> PUZZLE



Vladimir Zolotykh <gsmith@xxxxxxxxxxxxx> writes:

> Peter Seibel wrote:
>> Vladimir Zolotykh <gsmith@xxxxxxxxxxxxx> writes:
>>
>>>The following simple function
>>>(defun foo (n)
>>> (let* ((*print-right-margin* n)
>>> (a '("Whan" "you're" "lost" "in" "the" "Wild,"
>>> "and" "you're" "scared" "as" "a" "child,"
>>> "And" "Death" "looks" "you" "bang"
>>> "in" "the" "eye,")))
>>> (format t "~@<~{~A~^ ~}~:@>" a)))
>>>if called (cl-user::foo 10)
>>>prints one word at a line. So does (cl-user::foo 20),30,40.
>>>And only (cl-user::foo 50) prints
>>>
>>>Whan you're lost in the Wild, and you're scared
>>>as a child, And Death looks you bang in the eye,
>>>
>>>What's wrong? I'd expect that calls with n less that 50 (e.g 20, 30, 40)
>>>would also print _formatted_ paragraph. Where was I wrong?
>> I'm sure I don't actually understand this but poking around a bit I
>> came up with this:
>> (defun foo (n)
>> (let ((*print-right-margin* n)
>> (*print-miser-width* nil)
>> (a '("Whan" "you're" "lost" "in" "the" "Wild,"
>> "and" "you're" "scared" "as" "a" "child,"
>> "And" "Death" "looks" "you" "bang"
>> "in" "the" "eye,")))
>> (format t "~@<~;~{~A~^ ~}~;~:@>" a)))

> Yes, it's kikd of a mistery. I sure understand less then nothing in
> the HyperSec section for *PRINT-MISER-WIDTH*, what's the "miser
> style" of output mentioned there?

So my vague recollection from reading one of the original papers about
the XP pretty printer (upon which the CL pretty printer is based) is
that the miser-width controls what happens when there's less than
*print-miser-width* columns left until the right margin. The point is
that after you've printed a bunch of levels of stuff (say when you're
printing s-expressions) and the natural indentation has pushed things
over to the right, it can't possibly print things at full width so it
switches over to "miser mode" which is miserly with horizontal space,
i.e. it breaks lines more often.

In both Allegro and OpenMCL (running in SLIME which maybe has
something to do with it) *PRINT-MISER-WIDTH* was set to 40. So when
you set *PRINT-RIGHT-MARGIN* to 40 or less the number of columns left
was less than *PRINT-MISER-WIDTH* so it switches to miser mode and
breaks the lines a lot more than would otherwise be required. But when
*PRINT-RIGHT-MARGIN* was 50 it was greater than *PRINT-MISER-WIDTH*
and, since you start printing in column 0, there was enough space to
print in normal mode.

Anyway, that's how I understand it upon a bit of reflection.

-Peter

--
Peter Seibel * peter@xxxxxxxxxxxxxxx
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
.