Formatting 我怎样才能正确地表达我的;格式";功能?
我有一个功能:Formatting 我怎样才能正确地表达我的;格式";功能?,formatting,common-lisp,Formatting,Common Lisp,我有一个功能: (defun play (&rest args) (format nil "play ~A~{, ~A~}~%" (car args) (cdr args)))) 而且,据我所知,应该这样使用: (play 1 2 3) (format t "~:[not playing anything~;play ~{~a~^, ~}~]" args args) 在本例中,返回“播放1 2 3”。不幸的是,此代码中有一些错误,因此我的
(defun play (&rest args)
(format nil "play ~A~{, ~A~}~%" (car args) (cdr args))))
而且,据我所知,应该这样使用:
(play 1 2 3)
(format t "~:[not playing anything~;play ~{~a~^, ~}~]" args args)
在本例中,返回“播放1 2 3”。不幸的是,此代码中有一些错误,因此我的emacs编辑器返回以下内容:
main.lisp:7:7:
error:
don't know how to dump #<SWANK/GRAY::SLIME-OUTPUT-STREAM {1004139673}> (default MAKE-LOAD-FORM method called).
==>
#<SWANK/GRAY::SLIME-OUTPUT-STREAM {1004139673}>
note: The first argument never returns a value.
note:
deleting unreachable code
==>
"play ~A~{, ~A~}~%"
main.lisp:7:7:
错误:
不知道如何转储#(调用默认的MAKE-LOAD-FORM方法)。
==>
#
注意:第一个参数从不返回值。
注:
删除无法访问的代码
==>
“播放~A~{,~A~}~%”
你能帮我写这个函数吗?你的例子对我也很有用(尽管它是人为的,请看注释) 但是,这里有一个使用外部库的示例,如果/当您不记得格式指令时
;; (ql:quickload "str")
(format t "play ~a" (str:join ", " (list 1 2 3)))
;; => play 1, 2, 3
你的例子也适用于我(尽管它是人为的,请参见注释) 但是,这里有一个使用外部库的示例,如果/当您不记得格式指令时
;; (ql:quickload "str")
(format t "play ~a" (str:join ", " (list 1 2 3)))
;; => play 1, 2, 3
错误
在代码中,您可以编写:
(defun play (&rest args)
(format #.*standard-output* "play ~A~{, ~A~}~%" (car args) (cdr args))))
在对代码求值之前,首先读取代码:将源代码转换为抽象语法树,以lisp值表示。遇到#。*标准输出*
,读取器计算下一个表单,这里是*标准输出*
:读取表单时绑定到此变量的实际流存储在结构化表达式中,该表达式是函数play
的源代码
您可以在代码中放入任意数据,特别是字符串、数字等。在这里,您的源代码包含一个流实例。当您尝试执行函数play
时,这可能是一个问题,因为在您计算函数体时,流可能已关闭;看起来您正试图修复要将输出写入的流,但这可能不是一个好方法。如果您编辑您的问题以添加更多相关信息,我们可能会找到更好的方法来解决您的问题
在编译代码时,存储流对象也是一个问题,这可能是这里出现此特定错误的原因
如注释中所述,编译文件时会发生这种情况。如果使用Slime,当环境使用临时文件编译缓冲区时,可能会发生这种情况
因此,在使用时会发生错误;特别注意规范中的本段:
要由文件编译器编译的程序必须只包含可外部化的对象;有关此类对象的详细信息,请参见第3.2.4节(编译文件中的文字对象)。有关如何扩展可外部化对象集的信息,请参阅函数make load form和第3.2.4.4节(可外部化对象的附加约束)
文件编译器生成一个对象文件(fasl扩展名)。某些文字值(如常量字符串等)必须存储在生成的文件中,以便在加载回文件()时可以重构类似的对象。对于大多数标准类型,Lisp编译器知道如何转储对象并将其加载回
但是在这里,编译器不知道如何在编译过程中转储stream
类型的值。您可以为定义方法,但某些数据本身很难(反)序列化:我们如何存储线程或任何其他操作系统资源
格式
除了在读取时评估*标准输出*
之外,该格式有效
但是,您可以将列表分解为其car
和cdr
,但是:
args
为NIL,则打印文本为“play NIL”
,这与一个元素NIL的列表不明确;或者,您可能只使用非空列表调用函数,在这种情况下,您可能应该添加(check type list cons)
,以便更好地捕获编程错误。或者,定义play
,如下所示:
(defun play (arg &rest more-args)
...)
然后,ARG
是car,MORE-ARGS
是cdr,用户不能使用空的ARGS列表调用函数(约束在函数签名中也更明确)
format
本身已经可以处理的事情
(format t "~{~a~^, ~}" args)
如果正在处理的列表中没有剩余元素,则插入符号操作符将以格式退出当前迭代上下文。所以在这里,我们只在列表中有更多元素时添加逗号和空格。
此外,您可能希望处理空列表并打印其他内容,如如果列表为空,则不播放任何内容
;在这种情况下,使用以下构造:
"~:[ ... ~; ... ~]"
带有冒号修饰符的方括号运算符类似于if,即~之前的部分
用于NIL情况,即~代码>用于非零部件;您需要这样写:
(play 1 2 3)
(format t "~:[not playing anything~;play ~{~a~^, ~}~]" args args)
请注意如何两次提供args
:首先用于测试,然后(仅)在测试的真正分支中使用它。通过让format在其参数列表上倒带,我们可以做得更好,这样它就可以使用单个参数args
两次:
(format t "~:[not playing anything~;~:*play ~{~a~^, ~}~]" args)
带有冒号修饰符~:*
的星号运算符通过返回所提供参数列表中的一个参数来更改格式
正在使用的当前参数
(defun play (&rest args)
(format #.*standard-output* "play ~A~{, ~A~}~%" (car args) (cdr args))))
在对代码求值之前,首先读取代码:将源代码转换为抽象语法树,以lisp值表示。遇到#。*标准输出*
,读取器计算下一个表单,这里是*标准输出*
:读取表单时绑定到此变量的实际流存储在结构化表达式中,该表达式是函数play
的源代码
Y