gpt4 book ai didi

recursion - 用于嵌套循环的 Lisp 宏(或函数)

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

是否可以编写一个 Common Lisp 宏,它采用维度和变量列表、(迭代的)主体,并创建由列表指定的嵌套循环组成的代码?

也就是说,类似于:

(nested-loops '(2 5 3) '(i j k) whatever_loop_body)

应该扩展到

(loop for i from 0 below 2 do
(loop for j from 0 below 5 do
(loop for k from 0 below 3 do
whatever_loop_body)))

跟进

正如怀远正确指出的那样,我必须知道在编译时传递给宏的参数。如果你真的像我一样需要一个功能,请看下面。

如果您对宏没问题,请使用 6502 的递归解决方案,非常棒。

最佳答案

您不需要引号,因为维度和变量无论如何都需要在编译时知道。

(defmacro nested-loops (dimensions variables &body body)
(loop for range in (reverse dimensions)
for index in (reverse variables)
for x = body then (list y)
for y = `(loop for ,index from 0 to ,range do ,@x)
finally (return y)))

编辑:

如果维度不能在编译时决定,我们就需要一个函数

(defun nested-map (fn dimensions)
(labels ((gn (args dimensions)
(if dimensions
(loop for i from 0 to (car dimensions) do
(gn (cons i args) (cdr dimensions)))
(apply fn (reverse args)))))
(gn nil dimensions)))

并在调用时将主体包裹在 lambda 中。

CL-USER> (nested-map (lambda (&rest indexes) (print indexes)) '(2 3 4))

(0 0 0)
(0 0 1)
(0 0 2)
(0 0 3)
(0 0 4)
(0 1 0)
(0 1 1)
(0 1 2)
(0 1 3)
(0 1 4)
(0 2 0)
(0 2 1)
...

编辑(2012-04-16):

以上版本的 nested-map 是为了更准确地反射(reflect)原始问题陈述而编写的。正如 mmj 在评论中所说,使索引范围从 0 到 n-1 可能更自然,如果我们不坚持以行为主的迭代顺序,则将反转移出内部循环应该会提高效率。此外,让输入函数接受一个元组而不是单个索引可能更明智,以便与排名无关。这是一个具有所述更改的新版本:

(defun nested-map (fn dimensions)
(labels ((gn (args dimensions)
(if dimensions
(loop for i below (car dimensions) do
(gn (cons i args) (cdr dimensions)))
(funcall fn args))))
(gn nil (reverse dimensions))))

然后,

CL-USER> (nested-map #'print '(2 3 4))

关于recursion - 用于嵌套循环的 Lisp 宏(或函数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10163298/

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