我想编写一个检查列表的递归函数,如果列表按升序排列则返回true,否则返回NIL。如果列表为空,则仍然如此。我是Lisp的新手,所以它仍然非常令人困惑。
(defun sorted (x)
(if (null x)
T
(if (<= car x (car (cdr x)))
(sorted (cdr x))
nil)))
答案 0 :(得分:1)
递归版:
(defun sorted (list)
(or (endp list)
(endp (cdr list))
(and (<= (first list) (second list))
(sorted (cdr list)))))
更加惯用的基于循环的谓词接受:test
参数:
(defun sortedp (list &key (test #'<=))
(loop for (a b) on list
while b
always (funcall test a b)))
接受:key
的版本;我们只对每个访问过的元素调用key
函数:
(defun sortedp (list &key (test #'<=) (key #'identity))
(loop for x in list
for old = nil then new
for new = (funcall key x)
for holdp = T then (funcall test old new)
always holdp))
一些测试:
(loop for k in '(()
((1))
((1) (2))
((2) (1))
((1) (2) (3))
((3) (2) (1)))
collect (sortedp k :test #'> :key #'car))
=> (T T NIL T NIL T)
这个也适用于其他类型的序列:
(defun sortedp (sequence &key (test #'<=) (key #'identity))
(reduce (lambda (old x &aux (new (funcall key x)))
(if (or (eq old t)
(funcall test old new))
new
(return-from sortedp nil)))
sequence
:initial-value t))
上述测试给出:
(T 1 NIL 1 NIL 1)
...由于广义布尔值,这是正确的结果。
答案 1 :(得分:1)
如果你正在做作业(似乎是这样),那么上面的答案都没问题。如果您只是学习Lisp,并且没有关于递归的约束,那么下面的内容可能会让您对Lisp的强大功能有所了解:
(defun sorted (l)
(or (null l) (apply #'< l)))
答案 2 :(得分:0)
您的解决方案的第一个问题是基本情况您需要停止在列表的末尾,但是当查看最后一个元素时,您需要元素来进行比较。调用(car x)
(defun sorted (list)
(if (endp (cddr list))
(<= (car list) (cadr list))
(and (<= (car list) (cadr list))
(sorted (cdr list)))))
请记住,在CL
中不鼓励使用递归解决方案