-1

我对 lisp 比较陌生,并且对在以下上下文中使用嵌套列表的最佳方法感到好奇:

所以,我有以下功能:

(defun get-p0 (points)
    (loop for (label x y) in points
    ; collect (list (if (> x y) (+ 2 3))))
    collect (list (get-angle (first points) (second points))))
)

我这样称呼它:

(get-p0 '((A 5 2) (B 2 3) (C 8 9)))

我一直在尝试做的是获取每个坐标相对于其他坐标的角度。例如,AB、AC、BA、BC、CA、CB 的角度并打印出来。我得到的输出如下:

((161.56505) (161.56505) (161.56505))

这实际上只是出于测试目的。虽然我真正想做的是输出最低和最左边的坐标。有任何想法吗?

4

3 回答 3

2

前段时间我做了非常相似的练习。这看起来可能对您有用:

;; Define struct `point'
(defstruct point x y)

;; Define methods specializing on `point'
(defgeneric add (a b))

(defgeneric subtract (a b))

(defgeneric distance (a b))

(defgeneric projection (a))

(defmethod add ((this point) (that point))
  (make-point :x (max (point-x this) (point-x that))
              :y (max (point-y this) (point-y that))))

(defmethod subtract ((this point) (that point))
  (make-point :x (min (point-x this) (point-x that))
              :y (min (point-y this) (point-y that))))

(defmethod distance ((this point) (that point))
  (let ((a (add this that)) (b (subtract this that)))
    (make-point :x (- (point-x a) (point-x b))
                :y (- (point-y a) (point-y b)))))

(defmethod projection ((this point))
  (sqrt (+ (expt (point-x this) 2) (expt (point-y this) 2))))

;; Define helper functions
(defun angle (a b c)
  (acos (/ (+ (* a a) (* b b) (- (* c c))) (* 2 a b))))

(defun radian->degree (radian) (/ (* 180 radian) pi))

;; Define struct `triangle'
(defstruct triangle
  (a nil :type (or null point))
  (b nil :type (or null point))
  (c nil :type (or null point)))

;; Define methods specializing on `triangle'
(defgeneric angles-of (triangle))

(defgeneric sides-of (triangle))

(defgeneric points-of (triangle))

(defmethod points-of ((this triangle))
  (let ((result (list (triangle-a this) (triangle-b this) (triangle-c this))))
    (nconc result result)))

(defmethod sides-of ((this triangle))
  (loop for (p . rest) on (points-of this)
     for i from 0 below 3
     collect (projection (distance p (car rest))) into result
     finally (return (nconc result result))))

(defmethod angles-of ((this triangle))
  (loop for (a b c) on (sides-of this)
       for i from 0 below 3
       collect (radian->degree (angle a b c)) into result
       finally (return (nconc result result))))

;; Create some test triangle
(defvar *pythagorean-triangle*
  (make-triangle :a (make-point :x 1 :y 2)
                 :b (make-point :x 4 :y 2)
                 :c (make-point :x 4 :y 6)))

;; Finally! don't forget to
(setf *print-circle* t)
;; so you can see circular lists' content
(angles-of *pythagorean-triangle*)

#1=(90.00000265626015d0 36.86989784081561d0 53.13009995842113d0 . #1#)

几条笔记,我在另一篇文章中看到表格有些混乱

(loop for <list-like expression> in some-list ...)

list-like expression就是通常所说的“解构绑定”。它是一种有限的模式匹配工具。实际上,这是一种模式,它将您在模式内定义的符号映射到您正在迭代的列表中找到的任何值。

因此,例如,(loop for (x y) on '(1 2 3 4))将和绑定xy12然后2,,,3然后34最后4nil。当然,您可以使用更多变量/您可以对模式使用点列表等。

于 2013-04-03T01:07:10.683 回答
1

If I understand your goal correctly, you want to consume a list like '((A 5 2) (B 2 3) (C 8 9)) and return something like (2 2) (point a has A y of 2 and point B has an x of 2, and these are the lowest coordinates). I'd do something like

(loop for (_l x y) in lst
        minimizing y into min-y minimizing x into min-x
        finally (return (list min-x min-y)))

loop is a deep and powerful construct, so I'd recommend you read through the relevant PCL chapter and the loop spec (it's very easy to forget a directive that might turn out to be perfect for a given situation). If you're new to Lisp, you may want to take a look at the entire book, actually.

于 2013-04-03T15:06:12.147 回答
1

您使用表单在每次迭代中正确绑定值for (x y z) in list。但是当您在下一行中进行收集时,您正在从list. 该值永远不会随着循环的评估而改变。

您应该将代码更改为如下所示:

(defun get-p0 (points)
  (loop
      for (label x y) in points
      collect (list (get-angle x y))))
于 2013-04-03T10:50:23.177 回答