将LET变量绑定到Lisp中的新值

时间:2015-02-16 03:17:38

标签: binding lisp common-lisp

我试图获取列表的最小值和最大值并将其作为缺点返回。

;;
;; 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是变量?

2 个答案:

答案 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)))))