【问题标题】:CLISP macro definition uses charset symbol, but compiling failsCLISP 宏定义使用字符集符号,但编译失败
【发布时间】:2014-03-23 10:27:13
【问题描述】:

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

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

【问题讨论】:

    标签: macros compilation common-lisp clisp


    【解决方案1】:

    问题

    问题是宏的默认参数应该是一个符号,而不是它的值。

    说明

    将对象用作宏默认参数对于自评估对象(如字符串、数字、关键字)是可以的,但对于更复杂的对象则不行。

    当你使用宏时,它会展开成代码

    ... :external-format #<ENCODING CHARSET:ISO-8859-1 :UNIX> ...
    

    CLISP 无法将其写入fas 文件(这只是一个文本文件)。

    解决方案

    (external-format charset:iso-8859-1) 替换为(external-format 'charset:iso-8859-1)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-31
      • 1970-01-01
      • 2017-01-06
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 2017-03-03
      相关资源
      最近更新 更多