我想使用format
将s表达式转换为带有前缀符号的字符串。如何使用format
完成此操作?
示例;
(format t "<insert format controls here>" (1 2 3) '*)
=> "1 * 2 * 3"
答案 0 :(得分:7)
此答案包含错误代码。
容易,只需使用custom formatters:
(format t "~/acquire/~/disseminate/" '(1 2 3) '*)
它们的定义如下:
(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)))
例如:
CL-USER> (format t "~/acquire/~/disseminate/" '(1 2 3) '*)
1 * 2 * 3
memory
变量在两个函数的词法范围内,这使它们可以通信数据。第一个存储列表,第二个使用列表。如果您从不调用第二个函数(或第一个函数为nil),则memory
被永久绑定到最后一个列表,这可能是一个问题。另请注意,您可能会遇到并发问题。 坦白说,这不是您想要做的最好的方法,但是它可以完成工作。您的要求。
答案 1 :(得分:5)
(format t "~{~A~^ * ~}" '(1 2 3))
;; 1 * 2 * 3
;; NIL
~{~}
:遍历列表。~A
:打印易于理解的( a 美观的)
~^
:仅当列表中有后继元素时才打印以下内容。*
:在周围的空白处加缀。我曾经问过类似的问题。您在末尾添加了'*
-因此,您还希望控制应使用join
列表元素的分隔符。查看以下链接-
@Sylwester给出了可接受的答案:Nicer pythonic `join` in common-lisp。
(他通过将第二个格式表达式注入格式表达式来做到这一点-非常优雅!-
这样就可以致电(join '(1 2 3) :sep " * ")
)。
答案 2 :(得分:4)
使用str库*:
(str:join " * " '(1 2 3))
;; "1 * 2 * 3"
此join
函数的定义如下:
(defun join (separator strings)
(let ((separator (replace-all "~" "~~" separator)))
(format nil
(concatenate 'string "~{~a~^" separator "~}")
strings)))
*无耻的晋升。
答案 3 :(得分:1)
这是我想出的解决方案。
(defun compile-arith (expr)
(format nil (concatenate 'string "~{~(~a~)~^ " (string (car expr)) " ~}")
(cdr expr)))
(compile-arith '(* 1 2 3))
=> "1 * 2 * 3"