逆引きxyzzy lisp(制御構造) - circleratio/xyzzy GitHub Wiki
- 条件判断(if, when, unless)
- 条件判断(cond)
- 逐次評価(and, or)
- 繰り返し(while)
- 繰り返し(loop)、繰り返しの脱出(return)
- 繰り返し(do)
- 繰り返し(for)
- 指定回数の繰り返し(dotimes)
- リストを使った繰り返し(dolist)
- 指定値までの繰り返し(upto)
- 指定値までの繰り返し(downto)
- 指定値までの指定ステップ毎に繰り返し(step)
(setq key 0)
(if (= key 0)
(print "equal")
(print "not equal"))
=> "not equal"
if の else 節が nil である場合には、when, unless を使うこともできる。
(setq a 2)
=> 2
(when (<= a 3)
(print "3 or smaller")
a)
nil
=> "3 or smaller"
1
(setq a 5)
=> 5
(unless (<= a 3)
(print "more than 3")
a)
=> "more than 3"
5
(setq key 3)
(cond ((= key 0) (print "0"))
((= key 1) (print "1"))
((= key 2) (print "2"))
(t (print "other")))
=> "other"
Lisp では and, or は制御構造であり、マクロで実装される。
and は、条件が不成立になるまで左から順に評価を繰り返した上で、すべての条件が真であれば t を返す。
and は、条件が成立するまで左から順に評価を繰り返した上で、すべての条件が偽であれば nil を返す。
(defun under_three (x)
(print x)
(< x 3))
(and (under_three 1) (under_three 2) (under_three 3) (under_three 4))
=> 1
2
3
nil
(or (under_three 1) (under_three 2) (under_three 3) (under_three 4))
=> 1
t
while は CL では定義されていないが,xyzzy lisp ではマクロとして定義されている.
(let ((result 1) (i 1) (max 4))
(while (<= i max)
(setq result (* result i)
i (1+ i)))
result)
=> 24
Lisp の loop は無限ループ。 抜けるためには return を使う。
(let ((result 1) (i 1) (max 4))
(loop
(if (> i max) (return))
(setq result (* result i)
i (1+ i)))
result)
=> 24
(do ((n 1 (1+ n)) (result 1) (max 4))
((> n max) result)
(setq result (* result n)))
=> 24
for はないので,マクロで定義. step はループごとに var に加える値,opは終了条件(var と end を比較).
(defmacro for ((var begin end &optional step op) &body body)
`(do ((,var ,begin))
((funcall (if ,op ,op #'>) ,var ,end))
,@body
(setq ,var (+ ,var (if ,step ,step 1)))))
(for (i 1 5)
(print i))
=> 1
2
3
4
5
nil
(for (i 1 5 2)
(print i))
=> 1
3
5
nil
(for (i 3 1 -1 #'<) (print i))
=> 3
2
1
nil
(dotimes (x 5) (print x))
=> 0
1
2
3
4
nil
(dolist (x '(0 1 2 3 4)) (print x))
=> 0
1
2
3
4
nil
このページで定義した for マクロを使う.
(defmacro upto ((var begin end) &body body)
`(for (,var ,begin ,end) ,@body))
=> upto
(upto (i 1 5)
(print i))
=> 1
2
3
4
5
nil
このページで定義した for マクロを使う.
(defmacro downto ((var begin end) &body body)
`(for (,var ,begin ,end -1 #'<) ,@body))
=> downto
(downto (i 5 1)
(print i))
=> 5
4
3
2
1
nil
このページで定義した for マクロを使う.
(defmacro step ((var begin end step) &body body)
`(let ((op (cond ((> ,begin ,end) #'<)
((< ,begin ,end) #'>)
(t #'=))))
(for (,var ,begin ,end ,step op) ,@body)))
=> step
(step (i 3 0 -1) (print i))
=> 3
2
1
0
nil