我试图获取列表的最小值和最大值并将其作为缺点返回。
;;
;; Find minimum and maximum of a list
;;
(defun min-max (l)
(let ((n 0) (min 0) (max 0) (size (numAtomsInList l)))
(loop (when (= n (- size 1)) (return))
(cond
((> (nth n l) (nth (+ n 1) l))) (setq min 5) ;(nth n l))
((< (nth n l) (nth (+ n 1) l))) (setq max 7) ;(nth n l))
(t (setq max n))
)
(incf n)
)
(cons min max)
)
)
在最小值和最小值之前运行没有SETQ的功能时它编译的最大变量很好,但我得到的结果(0。0) - 在LET中设置的原始值。使用SETQ,它给了我错误:
错误:尝试获取未绑定变量`SETQ&#39;。
的值当我循环浏览列表时,如何更改min和max的值?为什么在语法上它是正确的时候假设SETQ是变量?
答案 0 :(得分:3)
我相信您正在错误地将cond
正文中的表单分组。 cond
条款应该看起来像(CONDITION BODY)
;你有
(cond
((> (nth n l) (nth (+ n 1) l)))
(setq min 5)
;; etc
)
你想要
(cond
((> (nth n l) (nth (+ n 1) l))
(setq min 5))
;; etc
)
如果您来自Clojure背景,您会发现许多Common Lisp表单的分组与Clojure类似物不同。
如果您有类似
的内容,请扩展您所看到的精确错误的原因(cond
(setq x y))
cond
会尝试将setq
作为一个值进行评估,而不是作为一个有用的东西(回想一下,在Common Lisp中,符号可以同时具有函数和值绑定);它与编写(when setq x y)
相同,如果我们将值绑定到setq
,我们就不会再出现未绑定的变量错误。
? (let ((setq t) (x :x) (y :y)) (cond (setq x y)))
:Y
答案 1 :(得分:1)
除了Huw指出的问题之外,您的代码还存在严重的效率问题:它使用nth
,每次都需要遍历整个列表;实际上,您正在编写一个二次的算法。作为一般经验法则,除非您真正知道自己在做什么,否则不应将nth
与变量参数一起使用。
为了提高效率,您应该按顺序遍历输入列表,而不是从头开始。如果像我一样,你是一个老屁,你可以使用do
循环来做到这一点:
(defun min-max (l)
(let ((min (car l)) (max (car l)))
(do ((l (cdr l) (cdr l)))
((null l) (cons min max))
(when (< (car l) min) (setq min (car l)))
(when (> (car l) max) (setq max (car l))))))
如果您愿意,可以使用花哨的loop
thingie:
(defun min-max (l)
(let ((min (car l)) (max (car l)))
(loop for e in (cdr l)
do (when (< e min) (setq min e))
do (when (> e max) (setq max e)))
(cons min max)))
或者,在Scheme风格中,你可以使用尾递归(并忽略那些告诉你它不可移植的旧Common Lisp程序员):
(defun min-max-3 (l)
(let ((min (car l)) (max (car l)))
(labels
((mm (l)
(cond ((null l) (cons min max))
(t (when (< (car l) min) (setq min (car l)))
(when (> (car l) max) (setq max (car l)))
(mm (cdr l))))))
(mm (cdr l)))))