2016-10-05 31 views
1

我一直在嘗試瞭解如何在LISP中使用循環,但他們仍然看起來似乎沒有正常工作。我試着用下面的代碼:如何在LISP中使用循環

(loop for i from 0 to (list-length y) 
      (when (eq (values-list (nth i (car y))) 0) 
      (return-from checkZero t))) 

應該通過我的列表檢查,如果我的值等於0或不循環。如果它相等,那麼它應該從循環中退出並退出,否則它應該運行直到達到列表長度。我在想這個錯誤嗎?如果是的話,我該如何去解決這個問題?

(我不知道如果我的實際代碼工作或沒有,因爲我依然能以正確使用循環生成的錯誤處理,我無法找到使用循環網上很多很好的資源)

+1

左右'(當(EQ刪除括號... )(return-from ...))'這樣,當(eq ...)(從...返回)'並且在'(從...返回...)'之前放置一個'do'。 – Renzo

+4

[實用常用Lisp](http://www.gigamonkeys.com/book/)有一個叫做[LOOP for Black Belts]的循環章節(http://www.gigamonkeys.com/book/loop-for-black -belts.html)。在[The land of lisp](http://landoflisp.com/)中,你有一個[實用的備忘單](http://blog.idorobots.org/media/lolreview/3.png) – Sylwester

回答

4

循環中的主要問題是WHEN-表達式。還有,你可以寫兩種方式:

  1. 使用循環WHEN condition DO forms -clause:

    (loop for... 
         when (eq ...) do (return-from ...)) 
    
  2. 使用常規WHEN -macro循環DO -clause內:

    (loop for... 
         do (when (eq ...) 
          (return-from ...))) 
    

還有其他一些事情可以在你的代碼中修復。

  1. 當Lisp的事物命名,用言語之間劃線,而不是駝峯(check-zero而非checkZero)。
  2. 使用=進行一般數字比較,或使用ZEROP檢查數字是否爲零。 EQ用於檢查兩個對象是否是同一個對象。
  3. 您可以使用RETURN
  4. 我不太清楚你想用(VALUES-LIST (NTH ... (CAR ...)))成就的進行環回,但它不會去上班。如果您試圖簡單地循環顯示一組值(例如(1 2 3 4 5 6)),則應該使用循環FOR item IN list-clause。

所以,現在你應該是這樣的:

(defun check-zero (list) 
    (loop for item in list 
     when (zerop item) do (return t))) 

LOOP也有一個THEREIS condition -clause,您可以使用:

(defun check-zero (list) 
    (loop for item in list 
     thereis (zerop item))) 

這回只要它找到一個項目時滿足ZEROP。但是,有更簡單的方法來實現這一點。你可以使用MEMBER檢查,如果列表包含零:

(defun check-zero (list) 
    (member 0 list :test #'=)) 

CL-USER> (check-zero '(1 3 4 3 5 7)) 
NIL 
CL-USER> (check-zero '(1 3 4 3 0 5 7)) 
(0 5 7) 

這將返回一個廣義布爾值。也就是說,任何非NIL的值在Common Lisp中都被認爲是真的。

既然有一個謂語函數(ZEROP)檢查的對象是零,你也可以使用SOMEMEMBER-IF此:

(some #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> T 
(member-if #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> (0 45 6 7) 
+0

輕微的警告,如果要檢查的列表可能合法地包含非數字,請使用'equalp'(如果您希望0和0.0比較相等)或'eql'(如果您希望數字值和數字類型都相同),因爲'zerop '如果參數是非數字並且'='可能會發出錯誤信號。 – Vatine