2013-04-02 94 views
-1

我是比较新的Lisp和很好奇,以最好的方法在下列情况下使用嵌套列表的工作:正与嵌套列表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)) 

这真的只是在这一点上测试的目的。虽然我真的想要做的是输出最低和最左边的坐标。有任何想法吗?

回答

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,然后23,然后34最后4nil。当然,你可以使用更多的变量/你可以使用虚线列表模式等。

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)))) 
1

如果我正确理解你的目标,你想消费清单像'((A 5 2) (B 2 3) (C 8 9))和返回类似(2 2)(点具有2的y和点B有一个x为2,这些是最低的坐标)。我会做这样的事情

(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是一个深刻而强大的构造,所以我建议你通过relevant PCL chapterloop spec阅读(这是很容易忘记,可能会变成是一个完美的指令给定的情况)。如果你是Lisp的新手,实际上你可能想看看the entire book

+0

@wvxvw - Yup;那些特定的关键字在当时逃脱了我。修订。 – Inaimathi