2013-04-02 361 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