我昨天开始使用lisp编程,所以请原谅我是否犯了一些真正的新手错误。我正在尝试创建一个使用钟形三角形计算钟数的函数,并且我的递归三角函数无法正常工作。我也确定如果我的递归三角函数工作,我的递归钟函数也会以某种方式被破坏。
当我测试我的三角函数时,我得到输出:
(defun bell(l n)
(if(< n 1)(list 1))
(if (= n 1)(last l))
(bell (triangle (reverse l) (last l) (list-length l)) (- n 1))
)
(defun triangle(pL nL i)
(if(<= i 0)
(write "equals zero!")
(reverse nL)
)
(triangle pL (append (list (+ (nth i pL) (nth i nL))) nL) (- i 1))
)
(write (triangle '(1) '(1) 0))
=>
"equals zero!""equals zero!"
*** - NTH: -1 is not a non-negative integer
出于某种原因,它打印我的调试代码两次,即使该函数应该在第一次调用时满足我的基本情况。
答案 0 :(得分:3)
出于某种原因,它打印我的调试代码两次,即使该函数应该在第一次调用时满足我的基本情况。
它被打印两次,因为^[0-9]+$
没有按照你的想法做。第一个if测试为真,因此等于零!被打印。之后,调用三角函数的递归调用。测试再次为真(-1 <= 0),因此等于零!再次打印。最后,您会收到错误,因为使用-1调用if
函数。我强烈建议你使用一个好的lisp调试器。来自Lispworks的那个非常好。
老实说,我没有弄清楚你想用代码实现的目标。所以我写了我的:
nthcdr
理解实施的事情:
(defun generate-level (l &optional (result))
"given a list l that represents a triangle level, it generates the next level"
(if (null l) result
(if (null result)
(generate-level l (list (car (last l))))
(generate-level (cdr l) (append result
(list (+ (car l)
(car (last result)))))))))
(defun bell (levels &optional (l))
"generate a bell triangle with the number of labels given by the first parameter"
(unless (zerop levels)
(let ((to-print (if (null l) (list 1) (generate-level l))))
(print to-print)
(bell (1- levels) to-print))))
:此参数是可选的,默认为nil。&optional (parameter)
连接两个列表。我正在使用它插入列表的后面。append
创建一个名为let ((to-print x))
的新变量绑定(局部变量)并初始化为to-print
。x
在常见的lisp中是如何工作的:
if
表示如果(if (= x 1) y z)
等于1,则返回x
,否则y
。 现在,如果你调用函数来创建一个7级的Bell三角形:
z
使用适当的填充打印它会更好,如下所示:
CL-USER 9 > (bell 7)
(1)
(1 2)
(2 3 5)
(5 7 10 15)
(15 20 27 37 52)
(52 67 87 114 151 203)
(203 255 322 409 523 674 877)
NIL
但我把它作为练习留给了读者。
答案 1 :(得分:2)
您的 if 没有任何效果。他们被评估,并产生结果,但随后你丢弃它们。就像
(defun abc ()
'a
'b
'c)
会评估'a 和'b 以生成符号 a 和 b ,然后评估'c 生成符号 c ,然后返回。在
的情况下(if(<= i 0)
(write "equals zero!") ; then
(reverse nL) ; else
)
你正在比较 i 是否小于或等于零,如果是,你打印等于零,如果不是,你(非破坏性地)反转nL并丢弃结果。然后通过调用三角形来完成该功能。当i小于或等于零时,您可能希望返回反转的nL。请改用 cond ,因为您可以拥有多个正文表单,例如:
(cond
((<= i 0) (write ...) (reverse nL))
(t (triangle ...)))
您还可以使用 if 与预测对表单进行分组:
(if (<= i 0)
(progn
(write ...)
(reverse nL))
(triangle ...))
您的其他功能也有同样的问题。如果要在第一种情况下返回值,则需要使用实际返回它们的表单。例如:
(if (< n 1)
(list 1)
(if (= n 1)
(last l)
(bell #| ... |#)))
更多惯用语是 cond ,并使用列表而不是 l ,这看起来很像 1 :
(cond
((< n 1) (list 1))
((= n 1) (last list))
(t (bell #| ... |#)))
答案 2 :(得分:-1)
谢谢大家的解释。我最终得到了下面的代码。我意识到if块的工作方式类似于..
(if(condition)(execute statement)(否则执行此语句))
(defun bell(l n)
(if (< n 2)(last l)
(bell (triangle l (last l) 0) (- n 1))
)
)
(defun triangle(pL nL i)
(if(= i (list-length pL)) nL
(triangle pL (append nL (list (+ (nth i pL) (nth i nL)))) (+ i 1))
)
)
(write (bell (list 1) 10))