ANSI Common Lisp譯本筆記4

控制流

區塊


區塊的基本操作符:progn、block、tagbody

progn:對主體中的每個表達式依次進行求值,返回最後一個表達式的值。

如:

(progn
        (format t "a")
	(format t "b")
	(+ 1 1))
輸出爲:ab
23


block:像一個帶有名字及緊急出口的progn。第一個參數爲符號。可在block中使用return-from  符號跳出block。

例子:

(block head
	(format t "one")
	(return-from head 'over)
	(format t "two"))
輸出爲:one
OVER
由例子可以看出,block之後的符號爲block塊的名字,通過return-from block名字即可跳出block。
return-from:第一個參數爲區塊名,第二個參數爲:跳出時的返回值
若想不使用塊名,跳出當前塊,則可以使用return 返回值,即可。
1.許多接收一個表達式主體的操作符都隱含在一個叫做nil區塊中。
2.使用defun定義的函數,都隱含在一個與函數同名的區塊中。所以,在函數中可用return-from 跳出函數並返回值

語境

用來代替表達式分組的操作符是let
let:接收一個代碼主體,允許在代碼主體中設置新變量。第一個參數爲變量的初始過程。
如:(let ((x 1) (y 1)) (+ x y))→2
let創造出一個新的詞法語境,就像C語言中的代碼塊,在此語境中的變量爲局部變量。
注意:由let創建的變量值,不能依賴其他由同一個let創造的變量。

如:

(let ((x 1) 
	  (y x))
	(+ x y))

其中,第一個let創建了一個x變量,可以在let語境內使用,但不能將此變量用於此let中創建另一個變量的初始值。要想使用則需要用let*。

let*例子:

(let* (x 1)
		(y x)
		(+ x y))
輸出:2
其中,let*等價於
(let ((x 1)
     (let (y x)
	(+ x y)))

deftructuring-bind:這是一個通用化的let,是一個宏。接收單一變量,接收一個模式:一個或多個變量形成的樹,並將它們與某個實際的樹所對應部分做綁定。
例子:(destructuring-bind (w (x y) . z)'(a (b c) d e) (list w x y z))→(A B C (D E))

條件

if
格式:if 條件 語句1 語句2
說明:若條件爲真,則執行語句1,否則執行語句2

例子:

(defun max-my (x y)
	(if (> x y) x y))

測試代碼:

CL-USER> (max-my 1 2)

2

when
格式:when 條件 語句1 語句2 ....
說明:若條件滿足則開始執行when中的所有語句,返回最後一條語句的值

例子:

(defun say (flag)
	(when (equal flag "talk")
	  (format t "hello!")
	  (format t "What's your name?")))
測試代碼:

CL-USER> (say "talk")
hello!What's your name?
NIL

unless與when類似,when是條件爲真,執行語句。unless是條件爲假,執行語句

cond
格式:cond (條件1 語句1 條件2 語句2...)
說明:條件1爲真,執行語句1,否則判斷條件2是否爲真,爲真執行語句2,否則判斷條件3....

例子:

(defun my-num-range (x)
	(cond ((> x 10) (format t "~A>10~%" x))
		((> x 5) (format t "~A>5~%" x))
		((> x 0) (format t "~A>0~%" x))
		(t (format t "~A<0~%" x))))
測試代碼:

CL-USER> (my-num-range 4)
4>0
NIL

其中,cond可以理解爲只有當條件爲真時,纔會停止判斷,條件爲真的其後的語句。最後一句,應爲t永遠爲真,所以將此句作爲缺省的條件式。

case
格式:case 關鍵字變量 (關鍵字或關鍵字列表 語句)...
說明:關鍵字的值會和下面的每個關鍵字或在關鍵字列表中查找,若有相等的則執行其後的語句。缺省子句可用的鍵值可爲t或otherwise。

typecase與case相似,typecase的每個鍵值應爲類型修飾符。第一個參數與鍵值比較的函數使用typep。


迭代

do
格式:do (變量規格說明的列表) (條件 語句1) 語句2
說明:變量規格的說明列表爲:迭代變量名,迭代初始值,下一個迭代值。條件爲結束迭代的條件,當滿足條件時執行語句1並停止迭代,否則執行迭代體語句,即:語句2。

例子:

(defun do-test (x)
	(do ((i 0 (+ i 1)))
	    ((= i x) 'done)
	  (format t "~A," i)))
測試代碼:

CL-USER> (do-test 5)
0,1,2,3,4,
DONE
do*:do*與do的關係相當於let*和let的關係。

dolist

格式:dolist (迭代變量 列表 迭代結束返回值) 迭代體語句
說明:當迭代開始時,會從列表第一個元素開始,依次賦給迭代變量,然後執行迭代體語句,當迭代到列表最後一個元素之後,則返回迭代結束返回值。迭代結束返回值也可以是一個語句。

例子:

(defun dolist-test (lst)
  	(dolist (x lst (format t "~%list over"))
		(format t "~A," x)))
測試代碼:

CL-USER> (dolist-test '(1 2 3 4))
1,2,3,4,
list over
NIL

dotimes
格式:dotimes (迭代變量 N 迭代結束返回值) 迭代體語句
說明:給定一個整數N,則會從整數0開始,直到N-1

例子:

(defun dotimes-test (n)
	(dotimes (x n 'over)
		(format t "~A," x)))
測試代碼:

CL-USER> (dotimes-test 4)
0,1,2,3,
OVER

多值

values:將傳入的參數返回。若將values作爲函數的最後一個表達式,則values返回的值將作爲函數返回值

測試代碼:

CL-USER> (values 'a 1 (+ 1 1))
A
1
2

multiple-value-bind:接受多個值。若變量的數量大於數值的數量,剩餘變量爲nil。若數值的數量大於變量的數據,則多餘的值捨去。

測試代碼:

CL-USER> (multiple-value-bind (x y z) (values 1 2 3) (list x y z)) 
(1 2 3)
CL-USER> (multiple-value-bind (x y z) (values 1 2) (list x y z))
(1 2 NIL)
CL-USER> (multiple-value-bind (x y z) (values 1 2 3 4) (list x y z))
(1 2 3)

multiple-value-call:將多值作爲參數傳給函數。第一個參數爲函數,第二個參數爲多值

測試代碼:

CL-USER> (multiple-value-call #'+ (values 1 2 3))
6

mutiple-value-list:將傳入的多值創建一個列表並返回。


中止


catch與throw

使用catch定義一個標籤,在代碼任何地方,一個帶有特定標籤的throw都會導致catch的表達式直接返回。

例子:

(defun sup()
	(catch 'quit
	 (sub)
	(format t "aaa")))
(defun sub()(throw 'quit 'done))
測試代碼:

CL-USER> (sup)

DONE
發佈了79 篇原創文章 · 獲贊 20 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章