逆引きxyzzy lisp(制御構造) - circleratio/xyzzy GitHub Wiki

目次

条件判断(if, when, unless)

(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

条件判断(cond)

(setq key 3)

(cond ((= key 0) (print "0"))
      ((= key 1) (print "1"))
      ((= key 2) (print "2"))
      (t (print "other")))
=> "other" 

逐次評価(and, or)

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)

while は CL では定義されていないが,xyzzy lisp ではマクロとして定義されている.

(let ((result 1) (i 1) (max 4))
  (while (<= i max)
    (setq result (* result i)
	  i (1+ i)))
  result)
=> 24

繰り返し(loop)、繰り返しの脱出(return)

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)

(do ((n 1 (1+ n)) (result 1) (max 4))
    ((> n max) result)
  (setq result (* result n)))
=> 24

繰り返し(for)

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)

(dotimes (x 5) (print x))
=> 0 
   1 
   2 
   3 
   4 
   nil

リストを使った繰り返し(dolist)

(dolist (x '(0 1 2 3 4)) (print x))
=> 0 
   1 
   2 
   3 
   4 
   nil

指定値までの繰り返し(upto)

このページで定義した 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

指定値までの繰り返し(downto)

このページで定義した 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

指定値までの指定ステップ毎に繰り返し(step)

このページで定義した 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
⚠️ **GitHub.com Fallback** ⚠️