common-lisp
制御構造
サーチ…
条件付きコンストラクト
Common Lispでは、 if
は最も単純な条件文です。これは、フォームを有する(if test then [else])
とに評価されthen
場合にtest
真であり、 else
それ以外の場合。 else部分は省略することができます。
(if (> 3 2)
"Three is bigger!"
"Two is bigger!")
;;=> "Three is bigger!"
間の1つの非常に重要な違いif
Common Lispではとif
、他の多くのプログラミング言語では、CLのことであるif
表現、ない文です。このように、 if
フォームは、変数に割り当てられた引数リストなどで使用できる値を返します:
;; Use a different format string depending on the type of x
(format t (if (numberp x)
"~x~%"
"~a~%")
x)
Common Lispのif
は、C#や他の "中括弧"言語の三項演算子と同等と見なすことができます。
たとえば、次のC#式は次のとおりです。
year == 1990 ? "Hammertime" : "Not Hammertime"
そのyear
が整数を保持してyear
と仮定して、次のCommon Lispコードに相当します。
(if (eql year 1990) "Hammertime" "Not Hammertime")
cond
は別の条件付き構造体です。これは、 if
文の連鎖にいくらか類似しており、次の形式をとります。
(cond (test-1 consequent-1-1 consequent-2-1 ...)
(test-2)
(test-3 consequent-3-1 ...)
... )
より正確には、 cond
は0個以上の節があり、各節には1つのテストの後に0個以上の結果が続きます。 cond
構造体全体が、テストがnil
に評価されない最初の節を選択し、その結果を順番に評価します。結果の最後のフォームの値を返します。
(cond ((> 3 4) "Three is bigger than four!")
((> 3 3) "Three is bigger than three!")
((> 3 2) "Three is bigger than two!")
((> 3 1) "Three is bigger than one!"))
;;=> "Three is bigger than two!"
他の句があると評価しないかどうかを評価するために、デフォルトの句を提供するためにt
、あなたが使用して、デフォルトではtrueで句を追加することができますt
。これは概念的にはSQLのCASE...ELSE
と非常によく似ていますが、タスクを達成するためにキーワードではなくリテラルブールの真を使用します。
(cond
((= n 1) "N equals 1")
(t "N doesn't equal 1")
)
if
構文はcond
構文として書くことができます。 (if test then else)
と(cond (test then) (t else))
は等価です。
あなたが唯一の句が必要な場合は、使用when
またはunless
:
(when (> 3 4)
"Three is bigger than four.")
;;=> NIL
(when (< 2 5)
"Two is smaller than five.")
;;=> "Two is smaller than five."
(unless (> 3 4)
"Three is bigger than four.")
;;=> "Three is bigger than four."
(unless (< 2 5)
"Two is smaller than five.")
;;=> NIL
doループ
Common Lispのほとんどのループと条件付きの構文は、実際にはより基本的な構文を隠すマクロです。たとえば、 dotimes
とdolist
はdo
マクロに基づいて構築されます。 do
のフォームdo
次のようになります。
(do (varlist)
(endlist)
&body)
-
varlist
は、ループで定義された変数、初期値、各反復後にどのように変化するかで構成されます。 '変更'部分は、ループの最後に評価されます。 -
endlist
には、ループの終了時に返される終了条件と値が含まれます。終了条件は、ループの開始時に評価されます。
ここでは0から始まり、10まで(10を含まない)になります。
;;same as (dotimes (i 10))
(do (( i (+ 1 i))
((< i 10) i)
(print i))
そして、リストを移動するものがあります:
;;same as (dolist (item given-list)
(do ((item (car given-list))
(temp list (cdr temp))
(print item))
varlist
部分はlet
文の部分と似ています。複数の変数をバインドすることができ、ループ内にのみ存在します。宣言された各変数は、それ自身の括弧のセットにあります。リストに1と2がいくつあるかを数えます。
(let ((vars (list 1 2 3 2 2 1)))
(do ((ones 0)
(twos 0)
(temp vars (cdr temp)))
((not temp) (list ones twos))
(when (= (car temp) 1)
(setf ones (+ 1 ones)))
(when (= (car temp) 2)
(setf twos (+ 1 twos)))))
-> (2 3)
whileループマクロが実装されていない場合
(do ()
(t)
(when task-done
(break)))
最も一般的なアプリケーションでは、より特定のdotimes
とdoloop
マクロがはるかに簡潔です。