这是一个宏定义,它构造一个循环,每次循环时指定的变量名都绑定到指定文件中的新行:
(defmacro with-string-from-file ((in-string filename
&key (if-does-not-exist :error))
&rest body)
(let ((working-stream (gensym)))
`(with-open-file (,working-stream
,filename
:direction :input
:external-format charset:iso-8859-1
:if-does-not-exist ,if-does-not-exist)
(let* ((,in-string))
(when ,working-stream
(loop while (setf ,in-string (read-line
,working-stream
nil))
do ,@body))))))
(princ "test 1:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf"
:if-does-not-exist nil)
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
; Test 2 has not been introduced yet.
(princ "test 3:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf.nonexistent"
:if-does-not-exist nil)
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
(princ "test 4:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf.nonexistent")
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
输出:
test 1:
one line is "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)"
one line is "# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN"
one line is "nameserver 192.168.6.1"
one line is "search x441afea5.org"
test 3:
test 4:
*** - OPEN: File #P"/etc/resolv.conf.nonexistent" does not exist
无论是直接运行文件,还是首先编译文件然后运行编译文件,都可以使用。
现在我尝试向宏添加一个功能,以便我可以指定输入字符集:
(defmacro with-string-from-file ((in-string filename
&key (if-does-not-exist :error)
(external-format charset:iso-8859-1))
&rest body)
(let ((working-stream (gensym)))
`(with-open-file (,working-stream
,filename
:direction :input
:external-format ,external-format
:if-does-not-exist ,if-does-not-exist)
(let* ((,in-string))
(when ,working-stream
(loop while (setf ,in-string (read-line
,working-stream
nil))
do ,@body))))))
(princ "test 1:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf"
:if-does-not-exist nil)
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
(princ "test 2:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf"
:external-format charset:utf-8
:if-does-not-exist nil)
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
(princ "test 3:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf.nonexistent"
:if-does-not-exist nil)
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
(princ "test 4:") (terpri)
(with-string-from-file (the-string "/etc/resolv.conf.nonexistent")
(princ "one line is \"")
(princ the-string)
(princ "\"")
(terpri))
当我直接运行文件时,它可以工作:
test 1:
one line is "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)"
one line is "# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN"
one line is "nameserver 192.168.6.1"
one line is "search x441afea5.org"
test 2:
one line is "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)"
one line is "# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN"
one line is "nameserver 192.168.6.1"
one line is "search x441afea5.org"
test 3:
test 4:
*** - OPEN: File #P"/etc/resolv.conf.nonexistent" does not exist
但是当我尝试编译它时,我收到了这个错误:
;; Compiling file /u/home/clisp/experiments/y1.lisp ...
*** - PRINT: Despite *PRINT-READABLY*, #<ENCODING CHARSET:ISO-8859-1 :UNIX>
cannot be printed readably.
如何编译?我想用charset:
明确指定一个字符集,而不是将这些字符集名称与我的主命名空间中的符号冲突。
答案 0 :(得分:3)
问题是宏的默认参数应该是符号,而不是它的值。
将对象用作宏默认args对于自我评估对象(如字符串,数字,关键字)是可以的,但对于更复杂的对象则没有用。
使用宏时,它会扩展为代码
... :external-format #<ENCODING CHARSET:ISO-8859-1 :UNIX> ...
并且CLISP无法将其写入fas
文件(这只是一个文本文件)。
将(external-format charset:iso-8859-1)
替换为(external-format 'charset:iso-8859-1)
。