Menu

#53 add format directive calling finish-output

None
closed-rejected
format (1)
5
2017-08-25
2017-08-21
No

A common user interaction pattern (see, e.g., clhs.lisp) is

  (format *http-log-stream* "~&;; ~S(~S)..." 'get-clhs-map stream)
  (force-output *http-log-stream*)

It should be more compactly written as

  (format *http-log-stream* "~&;; ~S(~S)...~=" 'get-clhs-map stream)

Where ~= translates to finish-output rather than force-output and ~:= translates to force-output.

I don't think clear-output makes much sense in this context, but we might map ~@= to it for completeness.

Discussion

  • Sam Steingold

    Sam Steingold - 2017-08-21
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -7,6 +7,6 @@
     ```
       (format *http-log-stream* "~&;; ~S(~S)...~=" 'get-clhs-map stream)
     ```
    -Where `~=` translates to [`finish-output` rather than `force-output` ](https://stackoverflow.com/q/2078490/850781) and `~:=` translates to [`force-output`](http://clhs.lisp.se/Body/f_format.htm).
    +Where `~=` translates to [`finish-output` rather than `force-output` ](https://stackoverflow.com/q/2078490/850781) and `~:=` translates to [`force-output`]((http://clhs.lisp.se/Body/f_finish.htm).
    
     I don't think `clear-output` makes much sense in this context, but we might map `~@=` to it for completeness.
    
    • Group: -->
     
  • Bruno Haible

    Bruno Haible - 2017-08-21

    I am not particularly enthusiastic of extending the FORMAT facility:
    a) because already after ANSI standardization, the FORMAT facility is way overloaded: you can write long format strings but there is no room for comments, See CLtL2 page 620 ("Print Function for the Xapping Data Type").
    b) because a user who simply uses a function
    (defun http-log (formatstring &rest args)
    (apply #'format http-log-stream formatstring args)
    (finish-output http-log-stream))
    will have the same functionality, with the added benefits that it's portable across CL implementations and more readable.

     
  • Sam Steingold

    Sam Steingold - 2017-08-21

    Given that you added ~., I find your objection surprising.
    Your example is typical of what I am trying to avoid - extra verbosity and pessimisation.

     
  • Sam Steingold

    Sam Steingold - 2017-08-21
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -7,6 +7,6 @@
     ```
       (format *http-log-stream* "~&;; ~S(~S)...~=" 'get-clhs-map stream)
     ```
    -Where `~=` translates to [`finish-output` rather than `force-output` ](https://stackoverflow.com/q/2078490/850781) and `~:=` translates to [`force-output`]((http://clhs.lisp.se/Body/f_finish.htm).
    +Where `~=` translates to [`finish-output` rather than `force-output` ](https://stackoverflow.com/q/2078490/850781) and `~:=` translates to [`force-output`](http://clhs.lisp.se/Body/f_finish.htm).
    
     I don't think `clear-output` makes much sense in this context, but we might map `~@=` to it for completeness.
    
     
  • Sam Steingold

    Sam Steingold - 2017-08-21
     

    Last edit: Sam Steingold 2017-08-21
  • Bruno Haible

    Bruno Haible - 2017-08-21

    > Given that you added ~., I find your objection surprising.
    ~. (format-elastic-newline) is just a variant of ~& (format-fresh-line). Its motivation is that use of FRESH-LINE leaves too many blank lines; see http://www.cliki.net/ELASTIC-NEWLINE
    It was necessary to add it to FORMAT because it would have been too verbose to use #+clisp (ext:elastic-newline stream) instead of ~%.

    Whereas here, for format-finish-output, there is no existing format directive with which it would complete. And additionally, it's most often only used with specific streams (log files and interactive displays), which makes it more suitable to be encapsulated in a function.

    Btw. I wish none of them were in FORMAT, because these directives cannot be buffered in a string:
    (format stream fmt args) is not the same as (format stream "~A" (format nil fmt args))
    But that problem was already introduced with the pretty-print directives (that depend on the notion of column position of a stream).

     
  • Jörg Höhle

    Jörg Höhle - 2017-08-22

    because these directives cannot be buffered in a string

    I don't think it's a good idea, for the exact same "within-stream" vs "out of band" argument.
    Suppose one performs a refactoring of the form (format "...~=" #) to (format "Query: ~A" (format nil #)). An explicit FINISH-OUTPUT is clearly visible and must come last. A ~= to a string output stream would be a NOP, and the functionality would silently and subtly get lost!
    Well, perhaps an argument along "makes it too easy to subtly break one's SW" is a moot one...
    People might refactor properly as (format "Query: ~A~=" (format nil #)).

    If there were ways to hide this inside CLISP internal functions to make it more compact, it would be OK. But whatever FORMAT knows about becomes part of its public interface and while it's nice to use platform specific features, it's doubly nice to be able to identify them in source code, e.g. via their SYS or EXT package prefix. Unportable format directives are completely non-obvious and hard to find (because you wouldn't think about looking for them, not because "~=" cannot be grep'ed).

     

    Last edit: Jörg Höhle 2017-08-22
  • Sam Steingold

    Sam Steingold - 2017-08-25
    • status: open --> closed-rejected
    • assigned_to: Bruno Haible --> Sam Steingold
     

Log in to post a comment.