gpt4 book ai didi

macros - 嵌套在宏内的 let 中的 if 子句未按预期工作

转载 作者:行者123 更新时间:2023-12-02 05:13:42 24 4
gpt4 key购买 nike

好吧,首先这是我的第一个问题,所以我对任何不好的做法表示歉意,并且如果您告诉我我做错了什么,我会很感激。

我正在尝试编写一个宏来减少重复代码,即在 Common Lisp 中创建一个包、系统或代码文件,并在其名称中包含章节号。下面的代码是我所拥有的,当 :chapter-number 作为字符串传递时它工作得很好,但当它作为数字传递时会出错:

(defmacro with-open-chapter-file
((streamvar (component &key
(type "lisp")
(directory (sb-posix:getcwd))
chapter-number))
(&body body))
`(let ((chapter-number ,(if (numberp chapter-number) ; the problem is at this if clause.
(write-to-string chapter-number) ; My intention was to convert it to a string if it was a number or leave it as is otherwise.
chapter-number)))
(with-open-file (,streamvar (make-pathname
:name ,(if chapter-number ; the variable manipulated in the if clause is used in this expression
(concatenate 'string "chapter-" chapter-number "-" (string component))
component)
:type ,type
:defaults ,directory)
:direction :output)
,body)))

当我运行以下测试时:

(macroexpand-1 '(with-open-chapter-file (out ("pack" :chapter-number 10))
(format t "Hey!")))

我收到错误:

The value
10
is not of type
SEQUENCE
[Condition of type TYPE-ERROR]

以及回溯:

  0: (LENGTH 10)
1: (SB-KERNEL:%CONCATENATE-TO-STRING "chapter-" 10 "-" "pack")
2: ((MACRO-FUNCTION WITH-OPEN-CHAPTER-FILE) (WITH-OPEN-CHAPTER-FILE (OUT ("pack" :CHAPTER-NUMBER 10)) (FORMAT T "Hey!")) #<unused argument>)
3: ((FLET SB-IMPL::PERFORM-EXPANSION :IN MACROEXPAND-1) #<FUNCTION (MACRO-FUNCTION WITH-OPEN-CHAPTER-FILE) {2278173B}> NIL)
4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (MACROEXPAND-1 (QUOTE (WITH-OPEN-CHAPTER-FILE # #))) #<NULL-LEXENV>)
5: (EVAL (MACROEXPAND-1 (QUOTE (WITH-OPEN-CHAPTER-FILE # #))))

如果你们能帮助我,我将非常感激。

最佳答案

在代码中:

  :name ,(if chapter-number ; the variable manipulated in the if clause is used in this expression
(concatenate 'string "chapter-" chapter-number "-" (string component))
component)

您正在使用宏的 chapter-number 参数,而不是在扩展中使用 let 绑定(bind)的变量,因为此代码位于逗号之后。

您不应该在扩展中绑定(bind)该变量,您应该只更新宏本身中的变量。

(defmacro with-open-chapter-file
((streamvar (component &key
(type "lisp") (directory (sb-posix:getcwd)) chapter-number))
(&body body))
(when (numberp chapter-number)
(setq chapter-number (write-to-string chapter-number)))
`(with-open-file (,streamvar (make-pathname
:name ,(if chapter-number
(concatenate 'string "chapter-" chapter-number "-" (string component))
component)
:type ,type
:defaults ,directory)
:direction :output)
,@body))

另一个不需要测试 chapter-number 类型的解决方案是将使用 concatenate 的代码更改为使用 format:

(if chapter-number
(format nil "chapter-%A-%A" chapter-number component)
component)

一个不相关的错误是您应该使用 ,@body 来替换正文,因为它是一个必须拼接到表达式中的列表。

关于macros - 嵌套在宏内的 let 中的 if 子句未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56572560/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com