Recursion Lisp:如何打印递归函数以打印列表和子列表中的每个项目(不带引号),并返回项目数?
我希望我的函数打印列表和子列表中的每个项目,不带引号,并返回项目数。列表的输出也需要有序,但我的函数是反向打印。我不知道为什么,有什么原因吗?对于如何递归计算项目数量并返回该数字,有什么建议吗?另外,为什么最后打印的项目应该是9.99而不是100.999 编辑:谢谢你到目前为止的帮助。最后一个问题:有没有办法让像DAY这样的输出用小写(DAY)表示,或者这是不可能做到的 我的职能:Recursion Lisp:如何打印递归函数以打印列表和子列表中的每个项目(不带引号),并返回项目数?,recursion,lisp,common-lisp,Recursion,Lisp,Common Lisp,我希望我的函数打印列表和子列表中的每个项目,不带引号,并返回项目数。列表的输出也需要有序,但我的函数是反向打印。我不知道为什么,有什么原因吗?对于如何递归计算项目数量并返回该数字,有什么建议吗?另外,为什么最后打印的项目应该是9.99而不是100.999 编辑:谢谢你到目前为止的帮助。最后一个问题:有没有办法让像DAY这样的输出用小写(DAY)表示,或者这是不可能做到的 我的职能: (defun all-print (inlist) (cond ((not (listp
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
我的输出示例:
CL-USER 1 > (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
100.999 -5.9 DAY -10 9 3 night 5
NIL
5 night 3 9 -10 day -5.9 9.99 ;print
8 ;returns
假设输出的内容示例:
CL-USER 1 > (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
100.999 -5.9 DAY -10 9 3 night 5
NIL
5 night 3 9 -10 day -5.9 9.99 ;print
8 ;returns
它看起来像是
所有的print
都应该被调用ffn
,因为它看起来像是递归调用。在这个答案的其余部分,我将使用ffn
,因为它比较短
为什么输出是相反的
目前,您的finalcond
子句在进行任何打印之前进行递归调用,因为您的递归调用是format
的参数:
(format t "~a " (car inlist) (ffn (cdr inlist)))
; ------------ -----------------
; 3rd 4th
在调用format之前,将对format
的所有参数(包括本例中的第4个)进行求值。这里的第4个参数将打印列表的其余部分,然后format
将最终打印列表的第一个元素。最后一个cond
子句应该进行打印,然后进行递归调用:
(cond
…
(t
(format t "~a " (car inlist))
(ffn (cdr inlist))))
为什么你得到的是100.999而不是9.99
您在输出中得到的是100.999,而不是9.99(或接近它的值),因为(*100.999)
的值只是100.999
的值。我猜您想要(*10 0.999)
(注意10
和0.99
之间的空格)。不过,由于浮点运算的原因,这仍然不会达到9.99,但会很接近
如何获得打印的元素数
这里提供了一个很好的解决方案。如果要返回打印的元素数,那么此函数的每个返回值都应该是一个数字。你有四个案子
- 不是列表-返回
不是一个好主意。如果无法返回数字(如0),则发出实际错误信号(如使用nil
)(错误“~a不是列表中的列表)”
- inlist为空-返回0(您已经这样做了)
是一个列表-在这里您对(car-inlist)
进行递归调用。因为合同上说它将返回一个计数,所以您就没事了。这是它在第一种情况下如此重要的原因之一(不是列表)您不返回非号码;合同取决于每个返回号码的呼叫ffn
- 在最后一种情况下,您打印一个项目,然后对
进行递归调用。该递归调用返回打印的剩余元素数,并且由于您刚刚打印了一个,因此您需要向其中添加一个。因此,finalffn
子句实际上应该如下所示。(向某个对象添加一个对象非常常见,以至于common Lisp有一个函数。)cond
((ab c)de f)
的内容时,您可以创建列表(ab c d e f)
,并在其上递归。但是,您可以在(ab c)
和(de f)
上等价地递归,并将结果添加在一起。这样可以避免使用append
创建新列表
不要检查参数类型
您正在检查输入是否是一个列表,但实际上不太需要这样做。如果输入不是列表,则对其使用列表处理函数将发出类似错误的信号
新版本
这有点类似于,但我对如何处理某些事情做了一些不同的选择。我使用一个本地函数process element
来处理每个输入列表中的元素。如果元素是一个列表,那么我们递归地将其传递给print all
,并返回递归调用的结果。否则,我们返回one并打印值。(我使用(prog1 1…
强调我们返回一个,而打印只是一个副作用。print all
的主要部分现在是一个典型的递归
(defun print-all (list)
(flet ((process-element (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x)))))
(if (endp list)
0
(+ (process-element (first list))
(print-all (rest list))))))
当然,现在我们已经拉出了辅助函数,迭代更清晰了,我们看到这实际上是一个例子。您甚至可以选择取消局部函数,只使用lambda函数:
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
以下是我对如何编写此函数的建议:
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
然后