Gwa*_*Kim 4 lisp metaprogramming common-lisp
在Edi Weitz的cl cookbook中,对于pythonic join
,建议使用此功能:
(defun join (separator list)
(with-output-to-string (out)
(loop for (element . more) on list
do (princ element out)
when more
do (princ separator out))))
Run Code Online (Sandbox Code Playgroud)
然而,不知何故,我在思考,必须有一种方式以join
另一种方式表达,也许使用format
的能力......
在Seibel的书中,(在章节中format
)我们发现将列表中的字符串连接到带有分隔符的单个字符串
", "
:
(defvar l '("a" "b" "c"))
(format nil "~{~A~^, ~}" l)
;; "a, b, c"
Run Code Online (Sandbox Code Playgroud)
这是一个pythonic连接,非常简洁; 该~^
指令使得", "
只添加到最后一个元素之前,并且在没有元素跟随时添加.
但是,这里,分隔符字符串", "
是format指令的一部分.
一个棘手的案例是例如(defvar sep #\Tab)
.如果sep的表示"#\Tab"
可以在此格式指令中作为分隔符放置,从而导致:
(format nil "~{~A~^#\Tab~}" l)
Run Code Online (Sandbox Code Playgroud)
我们会达到目标.
显然,必须使用宏来生成格式指令...我尝试了类似的东西,(princ-to-string sep)
但这给了"#\\Tab"
而不是"#\Tab"
.
例如
(defmacro join (sep l)
`(format nil ,(format nil "~{~A~}" `("\~\{\~A\~\^" ,(write-to-string sep) "\~\}")) l))
Run Code Online (Sandbox Code Playgroud)
但在尝试时:
(join #\Tab '("a" "b" "c"))
Run Code Online (Sandbox Code Playgroud)
这个结果当然是不希望的:"a#\\Tabb#\\Tabc"
因为
(macroexpand-1 '(join #\Tab '("a" "b" "c")))
;; results in:
(FORMAT NIL "~{~A~^#\\Tab~}" L)
;; instead of:
(FORMAT NIL "~{~A~^#\Tab~}" L)
Run Code Online (Sandbox Code Playgroud)
但是我没有看到如何实现这个步骤到所需的宏...有人对此有启发意义吗?
关于元编程问题的一种元编程...
好的,现在我知道,@ Rainer Joswig已经发布了以 什么方式加入列表中的字符串?
这个问题的解决方案.但是,如果有一种方法,表示"#\\Tab"
为"#\Tab"
,则可以得出更紧凑的定义.但不知何故,Lisp读者看起来总是被认为"\Tab"
是一个字母.是否可以编写一个函数来做到这一点?
备注
在R中,特别存在用于元编程的功能,例如从字符串"myvar" as.name("myvar")
生成符号myvar
.和表达式deparse(substitute(x))
,它采用符号x
并从中创建一个文字字符串"x"
.Deparse退回print()
命令的执行,从而转义特殊符号.deparse(deparse(substitute(x)))
会产生"\"x\""
- 虽然parse(text = ... )
围绕这个表达式会"x"
再次产生parse(text = deparse(deparse(substitute(x))))
.如何在普通的lisp中获得这样的东西?例如(a-special-function #\Tab)
导致(字面):"#\Tab"
作为字符串?
结语
谢谢@Sylwester !! 他没有宏就解决了.非常优雅!
您的问题是您尝试添加#\Tab
到格式,但这就是您如何使用文字.如果您只是在格式字符串中插入制表符或由其组成的字符串,它将执行您想要的操作:
(defun join (l &key (sep ", "))
(format nil (format nil "~a~a~a" "~{~a~^" sep "~}") l))
(join '(1 2 3))
; ==> "1, 2, 3"
(join '(1 2 3) :sep #\Tab)
; ==> "1 2 3"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
181 次 |
最近记录: |