gpt4 book ai didi

macros - 执行循环 "unrolling"的 Lisp 宏

转载 作者:太空宇宙 更新时间:2023-11-03 18:43:14 31 4
gpt4 key购买 nike

我使用 Lisp 宏的第一步......

(defconstant width 7)
(defconstant height 6)
...
; board is a 2D array of width x height
; and this is my first ever macro:
(defmacro at (y x)
`(aref board ,y ,x))
; "board" must be available wherever the macro is used.

(defun foo (board ...)
...
(loop for y from 0 to (1- height) do
; thanks to the "at" macro, this is cleaner:
(let ((score (+ (at y 0) (at y 1) (at y 2))))
(loop for x from 3 to (1- width) do
(incf score (at y x))
; ...do something with score
(decf score (at y (- x 3)))))))

该代码使用了我的第一个宏,“at”宏。它发出“访问指令”以从 board[y][x] 读取,因此它只能用于存在“board”的地方,如上面的函数“foo”。

这奏效了 - 然后我意识到......我可以走得更远。

两个嵌套循环是“静态”约束的:y 从 0 到 height-1,x 从 3 到 (width-1)...所以理论上,我可以创建一个宏来发出(展开!)在循环代码中完成的确切 incf 和 decf 指令!

我试过这个:

(defmacro unroll ()
(loop for y from 0 to (1- height) do
`(setf score (+ (at ,y 0) (at ,y 1) (at ,y 2)))
(loop for x from 3 to (1- width) do
`(incf score (at ,y ,x))
`(decf score (at ,y (- ,x 3))))))

...但失败了 - “(macroexpand-1 '(unroll))” 显示 NIL。

我做错了什么?

如果不清楚,我想使用两个嵌套循环并在外循环开始时发出“代码”,并针对内循环的每次迭代发出“代码”。

非常感谢任何帮助(我是 LISP 新手)。

更新:在@larsmans 的善意建议之后,我成功地将此更改应用到我的代码中 - 令我非常满意的是,我观看了我的 Score4 algorithm 的 Lisp 版本。成为第二快的实现,仅次于 C 和 C++(并且比 OCaml 更快!)。

最佳答案

您应该收集您在宏的循环中生成的语句,而不是假装用do执行它们:

(defmacro unroll ()
(loop for y from 0 to (1- height)
collect
`(begin (setf score (+ (at ,y 0) (at ,y 1) (at ,y 2)))
,@(loop for x from 3 to (1- width)
collect `(begin (incf score (at ,y ,x))
(decf score (at ,y (- ,x 3))))))))

关于macros - 执行循环 "unrolling"的 Lisp 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8022014/

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