关于lisp中使用递归函数的问题
Questions about using recursive functions in lisp
我是口齿不清的初学者。感谢Whosebug对我的帮助。
首先,我想用lisp函数表达递归函数。
没有编译错误,但是我想检查一下我写的代码语法是否正确
下面是我写的C代码
void queens(int i)
{
int j;
if (promising(i))
{
if (i == n)
{
//print all col list
return
}
else
{
for (j = 1; j <= n; j++)
{
col[i + 1] = j;
queens(i + 1);
}
}
}
}
下面是 lisp 代码。
(defvar n 4)
(defvar col (list 0 0 0 0 0 ))
(defun queens(i)
(let ((j 1))
(if (promising i)
(if (= i n) (print col)
(loop while (<= j n) do (setf (nth (+ 1 i ) col) j)
( queens (+ 1 i ) )
(incf j)))
)
))
首先,您(仍然)需要修复缩进、对齐和一般样式。这不仅是为了惹恼您,还因为它实际上 使事情更清晰,更容易调试。例如,如果缩进不正确,就很难看清每个表达式的结束位置,使用 loop
等复杂宏时情况更糟。您的代码,格式正确但没有任何其他修改,应该是:
(defun queens (i)
(let ((j 1))
(if (promising i)
(if (= i n)
(print col)
(loop while (<= j n)
do (setf (nth (+ 1 i) col) j)
(queens (+ 1 i))
(incf j))))))
- 右括号紧跟在表达式的最后一个形式之后,没有换行符,没有空格。
- 左括号也在表格的第一个元素之前,没有空格,但应该与前面的内容分开,除非它是另一个括号(所以
(defun queen (i) ...)
是正确的,而 ( defun queens(i))
违反了两条规则)。
- 当使用
if
结构时,要么将其写成 all 在一行中(条件、“then”形式和“else”形式) , 或者您必须在每个之后插入换行符。否则,不清楚“then”形式何时结束以及“else”何时开始。
- 当用
defvar
定义特殊变量时,用 '*' 来命名它们,如 (defvar *n* 4)
和 (defvar *col* (list ...))
.
另一个样式注意事项,有助于解决与嵌套相关的问题:如果您只对两个分支之一感兴趣,请使用 when
和 unless
而不是 if
。这使得意图清晰,并且还可以在复杂分支的情况下简化语法。
现在,对于代码:
如果您想使用 loop
,请使用基本的 for
结构。而不是写
(loop while (< j n) do ... (incf j))
使用
(loop for j from <start> to <end> do ...)
如果您想要稍微不同的终止条件,也可以使用 upto, below ...
。
执行此操作时,不需要使用 let
为 j
引入绑定,它将由循环引入。
如果要修改列表,请改用向量。不要将 col
定义为 (list ...)
,只需使用 (vector ...)
或 make-array
函数即可。之后,使用 elt
或 aref
访问单个元素,而不是仅适用于列表的 nth
。假定已考虑所有先前评论的代码版本:
(defun queens (i)
(when (promising i)
(if (= i n)
(print *col*)
(loop for j from 1 to *n*
do (setf (aref *col* (1+ i)) j)
(queens (1+ i))))))
不知道 promising
做什么以及 queens
应该做什么,很难给出更多的见解,但算法仍然很奇怪。例如,在对 (queens i)
的给定调用中,词法上明显的 setf
只会修改 col
的 i+1-th
单元格,将其设置为新的 j
在每次迭代中。据我所知,这只会导致 (aref col (1+ i))
在循环结束时被设置为 n
。似乎您也没有使用由 queens
递归地 return 编辑的值(这是意料之中的:您的 C 函数 return 什么都没有!),而且您实际上并没有这样做任何涉及 col
的检查,因此递归解决方案看起来很奇怪,(queens i)
和它在循环中调用 n
次的 (queens (1+ i))
之间(似乎)没有任何关系!
如果上面的段落无关紧要,因为 promising
也大量修改了 col
:停止做 C-in-Lisp 并停止到处修改。如果可以避免,不要依赖状态、突变、全局变量等。很容易定义递归解决方案,将列表作为参数传递给 return 多个值......因此通常不需要使用多个函数,每个函数都调用另一个函数,递归地修改共享的全局状态.乱七八糟,无法调试。
我是口齿不清的初学者。感谢Whosebug对我的帮助。
首先,我想用lisp函数表达递归函数。 没有编译错误,但是我想检查一下我写的代码语法是否正确
下面是我写的C代码
void queens(int i)
{
int j;
if (promising(i))
{
if (i == n)
{
//print all col list
return
}
else
{
for (j = 1; j <= n; j++)
{
col[i + 1] = j;
queens(i + 1);
}
}
}
}
下面是 lisp 代码。
(defvar n 4)
(defvar col (list 0 0 0 0 0 ))
(defun queens(i)
(let ((j 1))
(if (promising i)
(if (= i n) (print col)
(loop while (<= j n) do (setf (nth (+ 1 i ) col) j)
( queens (+ 1 i ) )
(incf j)))
)
))
首先,您(仍然)需要修复缩进、对齐和一般样式。这不仅是为了惹恼您,还因为它实际上 使事情更清晰,更容易调试。例如,如果缩进不正确,就很难看清每个表达式的结束位置,使用 loop
等复杂宏时情况更糟。您的代码,格式正确但没有任何其他修改,应该是:
(defun queens (i)
(let ((j 1))
(if (promising i)
(if (= i n)
(print col)
(loop while (<= j n)
do (setf (nth (+ 1 i) col) j)
(queens (+ 1 i))
(incf j))))))
- 右括号紧跟在表达式的最后一个形式之后,没有换行符,没有空格。
- 左括号也在表格的第一个元素之前,没有空格,但应该与前面的内容分开,除非它是另一个括号(所以
(defun queen (i) ...)
是正确的,而( defun queens(i))
违反了两条规则)。 - 当使用
if
结构时,要么将其写成 all 在一行中(条件、“then”形式和“else”形式) , 或者您必须在每个之后插入换行符。否则,不清楚“then”形式何时结束以及“else”何时开始。 - 当用
defvar
定义特殊变量时,用 '*' 来命名它们,如(defvar *n* 4)
和(defvar *col* (list ...))
.
另一个样式注意事项,有助于解决与嵌套相关的问题:如果您只对两个分支之一感兴趣,请使用 when
和 unless
而不是 if
。这使得意图清晰,并且还可以在复杂分支的情况下简化语法。
现在,对于代码:
如果您想使用 loop
,请使用基本的 for
结构。而不是写
(loop while (< j n) do ... (incf j))
使用
(loop for j from <start> to <end> do ...)
如果您想要稍微不同的终止条件,也可以使用 upto, below ...
。
执行此操作时,不需要使用 let
为 j
引入绑定,它将由循环引入。
如果要修改列表,请改用向量。不要将 col
定义为 (list ...)
,只需使用 (vector ...)
或 make-array
函数即可。之后,使用 elt
或 aref
访问单个元素,而不是仅适用于列表的 nth
。假定已考虑所有先前评论的代码版本:
(defun queens (i)
(when (promising i)
(if (= i n)
(print *col*)
(loop for j from 1 to *n*
do (setf (aref *col* (1+ i)) j)
(queens (1+ i))))))
不知道 promising
做什么以及 queens
应该做什么,很难给出更多的见解,但算法仍然很奇怪。例如,在对 (queens i)
的给定调用中,词法上明显的 setf
只会修改 col
的 i+1-th
单元格,将其设置为新的 j
在每次迭代中。据我所知,这只会导致 (aref col (1+ i))
在循环结束时被设置为 n
。似乎您也没有使用由 queens
递归地 return 编辑的值(这是意料之中的:您的 C 函数 return 什么都没有!),而且您实际上并没有这样做任何涉及 col
的检查,因此递归解决方案看起来很奇怪,(queens i)
和它在循环中调用 n
次的 (queens (1+ i))
之间(似乎)没有任何关系!
如果上面的段落无关紧要,因为 promising
也大量修改了 col
:停止做 C-in-Lisp 并停止到处修改。如果可以避免,不要依赖状态、突变、全局变量等。很容易定义递归解决方案,将列表作为参数传递给 return 多个值......因此通常不需要使用多个函数,每个函数都调用另一个函数,递归地修改共享的全局状态.乱七八糟,无法调试。