接受整数并创建二进制列表的递归函数。
我不明白为什么if(binlist 5)将输出(1011)哪个是正确的,而(binlist 10)的代码导致(append(binlist 5)'(0))没有给出(1010),而是给出(1010)。我甚至用Java写了同样的想法,结果成功了递归在Lisp中的工作方式不同吗或者是我遗漏了什么?
(defun binList(N)
(cond
((< N 1) '())
((= N 1) '(1))
((> N 1) (if(=(mod N 2) 0)
(append (binList(/ N 2)) '(0))
(append (binList(floor(/ N 2))) '(1))))))
最佳答案
您编写的代码实际上产生了正确的结果:
CL-USER> (binlist 10)
(1 0 1 0)
只是几个评论:
请使用Lisp名称约定:CL不区分大小写,所以
binList
只是BINLIST
,这里不算太糟,但bin-list
会更好。检查
(> n 1)
是多余的。考虑到这些注释,代码将如下所示:
(defun bin-list(n)
(cond ((< n 1) '())
((= n 1) '(1))
((zerop (mod n 2)) (append (bin-list (/ n 2)) '(0)))
(t (append (bin-list (floor (/ n 2))) '(1)))))
如果递归代码产生意外结果,首先要做的是跟踪它:
CL-USER> (trace bin-list)
(BIN-LIST)
CL-USER> (bin-list 10)
0: (BIN-LIST 10)
1: (BIN-LIST 5)
2: (BIN-LIST 2)
3: (BIN-LIST 1)
3: BIN-LIST returned (1)
2: BIN-LIST returned (1 0)
1: BIN-LIST returned (1 0 1)
0: BIN-LIST returned (1 0 1 0)
(1 0 1 0)
正如您所指出的,
(bin-list 10)
会导致(append (bin-list 5) '(0))
在这里您可以看到原始呼叫(呼叫0)(bin-list 10)
导致呼叫(bin-list 5)
(呼叫1)呼叫1返回(1 0 1)
最后,call 0将0
a追加到末尾。如果这不起作用,那么您可以调用调试器:请参见this blog以获取有关通用Lisp调试器(使用SLIME)的教程。