LISP 条件编程

LISP conditional programming

我正在尝试编写一个非常简单的程序,但虽然我无法理解,但请帮忙 假设我们有 10 个圆圈,每个圆圈都有 X、Y、Z、r 该程序将采用这些变量(x、y、z、r)并找出哪一对圆可以构成一个圆柱体(换句话说,哪些圆具有相同的 x、y、r(但不相同的 z)) 我应该使用什么样的命令? "cond if if....else if"


这是第一个代码:

(setq a 10)
(setq b 10)
(setq c 11)
(setq d 12)
(cond ((= a b) (cond ( (= b c) (print 'a=b=c)  )  )
(> a b) (print 'a>b)
(< a b) (print 'a<b))
)

我正在尝试将一个 COND 用作另一个 COND 中的一个动作,因此如果它们相同,我可以搜索这些数字,但似乎 lisp 不像 C 那样接受它...

当然,您可以根据需要嵌套 conds:

(defun funny-compare (a b c)
  (cond ((= a b)
         (cond ((= a c) 'all-equal)
               (t 'only-two-equal)))
        ((< a b) 'less)
        ((> a b) 'greater)))

这里有一些例子:

CL-USER> (funny-compare 1 1 1)
;;=> ALL-EQUAL
CL-USER> (funny-compare 1 1 2)
;;=> ONLY-TWO-EQUAL
CL-USER> (funny-compare 1 2 2)
;;=> LESS
CL-USER> (funny-compare 2 1 2)
;;=> GREATER

您只需要注意将相应的子句放入正确的 cond。自动缩进(以及匹配的括号和其他一些视觉辅助)使这变得非常微不足道。使用你在上面给出的代码并让 emacs 格式化它给我:

(cond ((= a b) (cond ( (= b c) (print 'a=b=c)  )  )
       (> a b) (print 'a>b)
       (< a b) (print 'a<b))
      )

仔细观察,你会发现所有的s表达式,从(= a b)开始到(< a b)(print 'a<b)都在相同的 括号组:分隔外部 cond 的括号。因此,所有这些表达式都是第一种情况的一部分,因此您只有一种情况。

你要的是这个:

(cond ((= a b)
       (cond ((= b c)
              (print 'a=b=c))))
      (> a b) (print 'a>b)
      (< a b) (print 'a<b))

仔细看缩进!

但是解决您最初的问题:您应该尝试在您的代码中表达您想要编程的想法。你写了 "circles" 之类的东西,但是你的代码没有表达任何这些(abc 等等很少是好名字)。

首先将您对圆的想法写入代码:

(defun make-circle (x y z r)
  (list x y z r))
(defun circle-x (circle)
  (first circle))
(defun circle-y (circle)
  (second circle))
(defun circle-z (circle)
  (third circle))
(defun circle-radius (circle)
  (nth 3 circle))

那么,你要检查的是多个独立的条件。你不需要多个 conds,事实上,明确地使用 and:

会更好
(cond ((and (= (circle-x one) (circle-x other))
            (= (circle-y one) (circle-y other))
            (= (circle-radius one) (circle-radius other))
            (not (= (circle-z one) (circle-z other))))
       'planar-not-same-but-on-axis-parallel-to-z))

请注意,这不是惯用的 lisp,因为写了很多本质上没有必要的东西,我们需要重复很多次。有很多工具(defclassdefstruct、访问器函数、with-slots、...)可用于缩短此时间。感谢列表的强大功能,我们甚至可以摆脱重复使用 =:

(flet ((extract (circle)
         (list (circle-x circle)
               (circle-y circle)
               (circle-radius))))
  (when (and (every #'= (extract one) (extract other))
             (not (= (circle-z one) (circle-z other))))
    'planaer-not-same-but-on-axis-parallel-to-z))

请注意,我也去掉了 cond,因为只有一个 case 的 cond 并不是很好的代码风格:只有当你有两个以上的分支时才使用它(例如两个分支使用 if).

希望对您有所帮助。

(defun make-circle (x1 y1 z1 r1)
(list x1 y1 z1 r1))
(defun circle-x (circle)
(first (make-circle x1 y1 z1 r1)))
(defun circle-y (x1 y1 z1 r1)
(second (make-circle x1 y1 z1 r1)))
(defun circle-z (x1 y1 z1 r1)
(third (make-circle x1 y1 z1 r1)))
(defun circle-radius (x1 y1 z1 r1)
(nth 3 (make-circle x1 y1 z1 r1)))
(cond ((and (= (circle-x 1 ) (circle-x 5 6 7 8))
        (= (circle-y one) (circle-y other))
        (= (circle-radius one) (circle-radius other))
        (not (= (circle-z one) (circle-z other))))
   'planar-not-same-but-on-axis-parallel-to-z))

这是你的代码,我做了一点改动,但我使用的在线编译器一直报错:CIRCLE-X:变量 X1 没有值