我是lisp的初学者。我很感激stackoverflow帮了我很多。
首先,我想使用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"形式(,要么必须在每一行之后插入换行符。否则;那么";形式结束;否则";启动 - 使用
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
递归返回的值(这是意料之中的:您的C函数什么都不返回!(,并且您也没有真正进行任何涉及col
的检查,因此递归解决方案看起来很奇怪,(queens i)
和它在循环中调用n
次的(queens (1+ i))
之间(似乎(没有关系!
如果上面的段落无关紧要,因为promising
也对col
进行了大量修改:停止在Lisp中使用C-in-Lisp,停止修改所有地方的内容。不要依赖状态,突变,全局变量&定义递归解决方案、将列表作为参数传递、返回几个值都很容易。。。因此,通常不需要使用多个函数,每个函数调用其他函数,递归地修改共享的全局状态。这一团糟,无法调试。