CLISP宏定义使用charset符号,但编译失败

时间:2014-03-23 10:27:14

标签: macros compilation common-lisp clisp

这是一个宏定义,它构造一个循环,每次循环时指定的变量名都绑定到指定文件中的新行:

(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:明确指定一个字符集,而不是将这些字符集名称与我的主命名空间中的符号冲突。

1 个答案:

答案 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)