关于在lisp中使用递归函数的问题

  • 本文关键字:递归函数 问题 lisp lisp
  • 更新时间 :
  • 英文 :


我是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 ...))中所示

另一个有助于解决嵌套相关问题的样式注意事项:如果您只对两个分支中的一个感兴趣,请使用whenunless,而不是if。这使意图变得清晰,并且在复杂分支的情况下也可以简化语法。

现在,对于代码:如果要使用loop,请使用基本的for构造。而不是写

(loop while (< j n) do ... (incf j))

使用

(loop for j from <start> to <end> do ...)

如果您想要不同的终止条件,也可以使用upto, below ...。执行此操作时,不需要使用letj引入绑定,它将由循环引入。

如果要修改列表,请使用向量。不要将col定义为(list ...),只需使用(vector ...)make-array函数即可。然后,使用eltaref来访问各个元素,而不是仅适用于列表的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只会修改coli+1-th单元,在每次迭代时将其设置为新的j。据我所知,这只会导致(aref col (1+ i))在循环结束时被设置为n。此外,您似乎没有使用queens递归返回的值(这是意料之中的:您的C函数什么都不返回!(,并且您也没有真正进行任何涉及col的检查,因此递归解决方案看起来很奇怪,(queens i)和它在循环中调用n次的(queens (1+ i))之间(似乎(没有关系!

如果上面的段落无关紧要,因为promising也对col进行了大量修改:停止在Lisp中使用C-in-Lisp,停止修改所有地方的内容。不要依赖状态,突变,全局变量&定义递归解决方案、将列表作为参数传递、返回几个值都很容易。。。因此,通常不需要使用多个函数,每个函数调用其他函数,递归地修改共享的全局状态。这一团糟,无法调试。

最新更新