Reputation: 389
I would like to convert an s-expression into a string with infix notation using format
. How can this be done using format
?
Example;
(format t "<insert format controls here>" (1 2 3) '*)
=> "1 * 2 * 3"
Upvotes: 3
Views: 141
Reputation: 38809
This answer contains bad code.
Easy, just use custom formatters:
(format t "~/acquire/~/disseminate/" '(1 2 3) '*)
They are defined as follows:
(let ((memory))
(defun cl-user::acquire (stream list &optional colonp atsignp)
(declare (ignore colonp atsignp stream))
(setf memory list))
(defun cl-user::disseminate (stream operator &optional colonp atsignp)
(declare (ignore colonp atsignp))
(format stream (concatenate 'string "~{~a~^ " (string operator) " ~}") memory)
(setf memory nil)))
For example:
CL-USER> (format t "~/acquire/~/disseminate/" '(1 2 3) '*)
1 * 2 * 3
The memory
variable is in the lexical scope of both functions, which allow them to communicate data. The first one stores the list, the second one uses it. If you never call the second function (or the first with nil), memory
is forever bound to the last list, that could be a problem. Note also that you could have concurrency issues. Frankly, this is not the best possible way to do what you want , but it gets the job done w.r.t. your requirements.
Upvotes: 7
Reputation: 389
Here is the solution I have come up with.
(defun compile-arith (expr)
(format nil (concatenate 'string "~{~(~a~)~^ " (string (car expr)) " ~}")
(cdr expr)))
(compile-arith '(* 1 2 3))
=> "1 * 2 * 3"
Upvotes: 1
Reputation: 18375
With the str library*:
(str:join " * " '(1 2 3))
;; "1 * 2 * 3"
This join
function is defined like so:
(defun join (separator strings)
(let ((separator (replace-all "~" "~~" separator)))
(format nil
(concatenate 'string "~{~a~^" separator "~}")
strings)))
* unshamed promotion.
Upvotes: 4
Reputation: 9865
(format t "~{~A~^ * ~}" '(1 2 3))
;; 1 * 2 * 3
;; NIL
~{~}
: Loop over list.~A
: Print human-readable (aesthetic)~^
: Print the following only if there is a successor element in list.*
: Infix with surrounding empty spaces.I was once asking a similar question. You added '*
at the end - so you want also control over which separator should join
the list elements. Look in the following link -
@Sylwester gave the accepted answer: Nicer pythonic `join` in common-lisp .
(He did it by injection of a second format expression into a format expression - very elegant! -
So that one can call (join '(1 2 3) :sep " * ")
).
Upvotes: 5