Robert Dodier
Robert Dodier

Reputation: 17576

Is it possible to get FORMAT to ignore undefined format directives?

I wonder if it is possible to tell FORMAT to ignore undefined format directives. I have looked at the pages for FORMAT in the CLHS but I don't see anything.

What I am trying to do is to get FORMAT to ignore ~m in a format string and just output ~m instead of trying to replace it with something. My plan is that at that point I will call another function which knows what to do with with ~m.

I guess a related question is then, is there a way to define a function to handle a format directive which is otherwise not defined?

In anticipation of some questions. (1) I guess a workaround would be to substitute a placeholder for ~m, and then substitute it back in afterwards and keep going. I guess I'll do that if all else fails. (2) I guess another general strategy would be to call the other function first, to handle ~m, then call FORMAT on the result. Unfortunately that other function recognizes some of the same directives, and barfs on others; it doesn't recognize only ~m and ignore everything else.

Upvotes: 1

Views: 107

Answers (3)

Capstone
Capstone

Reputation: 2282

From http://www.lispworks.com/documentation/lw50/CLHS/Body/22_c.htm

The control-string argument to format is actually a format control. That is, it can be either a format string or a function, for example a function returned by the formatter macro.

So you can do:

(defmacro frmt (control-string)
  (let ((str (cl-ppcre:regex-replace-all "~m" control-string "~~m"))) 
    `(formatter ,str)))

Now:

(format t (frmt "~m~A") 1)

outputs:

~m1
NIL

This way you don't have to modify the control string directly. You do have to modify the call to format to include frmt.

Upvotes: 1

user5920214
user5920214

Reputation:

I don't think there is a way of doing that portably (implementations may let you do all sorts of magic). I'd write a quote-weird-tildes and dequote-weird-tildes pair of functions and then write code like:

(defun format/qw (control &rest args)
  (declare (dynamic-extent args)
           (type string control))       ;can't be a function
  (dequote-weird-tildes
   (apply #'format nil (quote-weird-tildes control) args)))

Now you have a function which looks like (format nil ...) and is no harder to use than that. For extra value the quoting and dequoting functions should not cons a string if they don't have to.

Upvotes: 1

Leo
Leo

Reputation: 1934

You can define your own format directive with ~/name/, where name is the name of the function which is called. In your case you would have:

(format t "~/m/" 1)

(defun m (stream n colon-mod at-mod) 
   (format stream "~a" n)) ; or do something else with n

You still need to change the control string, but you can add a preprocessing step where "~m" is replaced by "~/m/".

Upvotes: 3

Related Questions