跳轉到內容

Common Lisp/外部庫/Iterate

來自華夏公益教科書,開放的書籍,開放的世界

Iterate 提供了一種類似於英語的迭代機制,就像 Common Lisp LOOP 設施一樣。這引發了一個問題 - 既然你已經內建了 LOOP,為什麼還要使用 Iterate?使用 Iterate 的最佳理由是它具有可擴充套件性。LOOP 非常靜態,但 Iterate 可以擴充套件到迭代你自己的資料結構,例如。

標準用法

[編輯 | 編輯原始碼]

正如你將看到的,Iterate 的語法非常像 LOOP。實際上,將 Iterate 視為帶有括號的 LOOP 通常是一個好主意。括號純粹是美觀的。括號背後的主要思想是為文字編輯器提供有關語法應如何格式化的提示,並使其更容易編寫擴充套件。

  • FOR 迴圈
;; Collect the values from 0 to 9
(iter (for i below 10)
      (collect i))

=> (0 1 2 3 4 5 6 7 8 9)

;; Collect the values from -5 to 10 stepping by PI
(iter (for i from -5 to 10 by pi)
      (collect i)

=> (-5.0d0 -1.8584073464102069d0 1.2831853071795862d0 4.424777960769379d0
 7.5663706143591725d0)

;; Find the number in the file that maximizes the square of itself.
(iter (for number in-file #p"file")
      (finding number maximizing (expt number 2)))

要獲取所有 iterate 結構的列表,請使用函式 DISPLAY-ITERATE-CLAUSES。

擴充套件 Iterates 功能

[編輯 | 編輯原始碼]

為了擴充套件 Iterate,你需要編寫一個新的驅動程式。

使用 DEFCLAUSE-SEQUENCE 和 DEFMACRO-DRIVER

[編輯 | 編輯原始碼]

DEFMACRO-CLAUSE

[編輯 | 編輯原始碼]

Iterate “陷阱”

[編輯 | 編輯原始碼]

由 iterate 在 FOR 驅動程式中完成的繫結實際上是透過 SET 完成的。這意味著在你收集一系列閉包時,你必須額外注意這些繫結變數。除非你顯式地進行詞法繫結,否則閉包將關閉被 iterate 修改的變數。最後,你將得到一個包含所有具有 iterate 退出時繫結的閉包的集合。

不要這樣做

(defparameter *closures*
  (iter (for number below 10)
        (collecting (lambda () number)) ))

==> *CLOSURES*

(funcall (first *closures*))

==> 10

這樣做

(defparameter *closures*
  (iter (for number below 10)
        (collecting (let ((number number))
                      (lambda () number)) )))

==> *CLOSURES*

(funcall (first *closures*))

==> 0

你應該注意 LOOP 的行為方式相同。

進一步閱讀

[編輯 | 編輯原始碼]
華夏公益教科書