top | item 33164208

(no title)

lapsed_lisper | 3 years ago

Richard P. Gabriel (one of the co-creators of Common Lisp, later a founder of the Lisp vendor, Lucid) has a few interesting things to say about CL's FORMAT in his Patterns Of Software, starting on page 101:

https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf

> What are the trade-offs? Format strings don’t look like Lisp, and they constitute a non-Lispy language embedded in Lisp. This isn’t elegant. But, the benefit of this is compact encoding in such a way that the structure of the fill-in-the-blank text is apparent and not the control structure.

IMO McDermott's OUT macro has precisely the drawbacks Gabriel predicts. While McDermott seems to think it's an advantage that

> we no longer have to squeeze the output data into a form intelligible to format, because we can use any Lisp control structure we like

his example PRINT-XAPPING basically duplicates the logic for extracting data from the xapping structure as Steele's FORMAT call, but buries the data extraction into control structure alongside constant strings that go into the output.

And that's where I think FORMAT really a win: a FORMAT control deliberately separates the control flow and constant text from the data extraction logic. Presumably you could write functions that do the same thing using McDermott's OUT macro, but they'll be more verbose and no more enlightening; what's the point?

discuss

order

interroboink|3 years ago

> what's the point?

I think there is some advantage to allowing comments to be nested alongside the relevant bits of format text.

It reminds me a bit of Perl's /x modifier[1], which arguably achieves some of the best of both worlds for regex expressions.

[1] https://perldoc.perl.org/perlre#/x-and-/xx

lapsed_lisper|3 years ago

Does it really make that much difference if comments exist "inside" the embedded sublanguage vs. "outside"? After all, you can always construct a format specification by string concatenation, and in CL, you can trick the parser into doing this for you:

  (format stream t
          #.(concatenate 'string
                         ;; comment about the first piece
                         <piece 1>
                         ;; comment about the second piece
                         <piece 2>)
          ...)
Additionally, for the record, CL's FORMAT is sufficiently hairy that you can achieve the effect of in-band comments if you wanted to:

  (format t "~
  ~0{ Because the previous line ended with a tilde, 
  the following newline is ignored. All of this text
  occurs inside an iteration construct that loops 
  zero times, so will not be output. However, it
  will consume one element from the list of arguments,
  so after this loop, we'll use tilde-colon-asterisk
  to back up one element, and let what comes next
  decide how to format it. So this is more or less
  a comment inside a CL FORMAT string.
  ~}~:*~
  ~S" 'Foo)

martinflack|3 years ago

I think what I'd really like is some way to expand format strings into McDermott-style code (and ideally vice versa).

I think CL-PPCRE gets this correct for a similar domain: regex strings. The library is not pedantic about whether you provide the compact string or an expanded nice version.

    PPCRE> (parse-string "(ab)*")
    (:GREEDY-REPETITION 0 NIL (:REGISTER "ab"))
    PPCRE> (scan '(:greedy-repetition 0 nil (:register "ab")) "ababcd")
    0
    4
    #(2)
    #(4)
    PPCRE>

lapsed_lisper|3 years ago

Out of curiosity, how often do you find yourself using CL-PPCRE's S-expression notation? (This is a genuine question: I've never felt a desire for an S-expression notation for regular expressions, so I'm curious what I'm missing out on.)

Anyhow, while it's certainly possible to parse FORMAT control strings into S-expressions, ISTM that if you want them to be invertible back into FORMAT strings, you'll end up with control structure and constant strings being contained within the S-expression, with data extraction as a separate concern. IOW, you won't get McDermott's preferred style of interwoven control, data extraction, and constant strings. For instance, you could have this FORMAT control string

  "~<~{~A~^, ~}.~:>"
parse to something like

  (:paragraph-fill ()
    (:iterate ()
       (:aesthetic)
       (:exit-if-list-exhausted)
       ", ")
    ".")
but this still separates concerns the way FORMAT does, and the way OUT doesn't.