Land Of Lisp 第4章

ここは条件文の章

if

 条件文ifで空リストのみ偽と判定
 空リストの表現は4つある
例. '() () 'nil nil

(eq '() nil)
t
(eq '() ())
t
(eq '() 'nil)
t

例. 条件判定の例 リストの長さ

(defun my-length (list)
  (if list
      (1+ (my-length (cdr list)))
    0))
my-length
(my-length '(list with four symbols))
4

listが変数名に使われていたが、
普通に使えるみたい。

その他条件の書き方

; 数値が等しい?
(= 1 2)
nil
(= 1 1)
t
; 奇数?
(oddp 5)
t
; 偶数?
(evenp 5)
nil


progn

 if文の1つの分岐で複数の処理を実施
例.

(if (oddp 5)
    (progn (setf *a* (+ 5 1))
      'odd)
  'even)
odd
*a*
6


when

 条件が真の場合に複数の処理を実施(暗黙のprogn)
 条件を見たさない場合はnilを返す。
例.

(when (oddp 5)
  (setf *b* 5)
  'odd)
odd
*b*
5

(when (oddp 4)
  (setf *b* 5)
  'odd)
nil

unless

 条件が偽の場合に複数の処理を実施(暗黙のprogn)
 条件を見たさない場合はnilを返す。
例.

(unless (oddp 4)
  (setf *c* 4)
  'even)
even
*c*
4

(unless (oddp 5)
  (setf *c* 4)
  'even)
nil


cond

 色々できる条件分岐
例.偶数の数を返す(自作)

(defun make-even-number (num)
  (cond ((oddp num) (princ num)
	 (princ " to ")
	 (princ (+ num 1)))
	(t (princ num)
	   (princ " is even number!"))))
make-even-number

(make-even-number 10)
10 is even number!
" is even number!"

(make-even-number 9)
9 to 10
10

*princ

t

 真

case

 ほかの言語でもよく見るcase
 比較にはeqlが使われるので文字列では比較できないらしい。
例.

(defun what-is-in (x)
  (case x
    ((1) '(1 is in x))
    ((A) '(A is in x))
    (("A") '(""A"" is in x))
    (otherwise '(what is this !))))
what-is-in

(defvar *x* 1)
*x*
(what-is-in *x*)
(1 is in x)
(defparameter *x* 'A)
*x*
(what-is-in *x*)
(A is in x)
(defparameter *x* "A")
*x*
(what-is-in *x*)
(what is this !)

*defvardefparameter


テクニック

andとor

例.

 (and t t nil)
nil
 (and t t t)
t
 (or t t nil)
t
 (or t t t)
t

これらは、C#の短絡評価のように働く
例.

(or (oddp 4) '(it is even))
(it is even)
(or (oddp 5) '(it is odd)) ; 後半は評価されない
t

(and (oddp 4) '(it is even)) ; 後半は評価されない
nil
(and (oddp 5) '(it is odd))
(it is odd)

こらは、できるというだけで真偽判定と処理は分けて書くのがよい。

member

 リストの中に要素が含まれるか調べる
 返すのは見つかった要素以降の部分リスト
例.nil以外は真とみなされる

(if (member 1 '(3 4 1 5))
    'in
    'no)
in
(member 1 '(3 4 1 5)
(1 5)

find-if

 条件付き検索
 関数には「#」をつける
例.

(find-if #'oddp '(2 4 5 6))
5
; ただしnullを使う場合は注意
(if (find-if #'null '(2 4 nil 6))
    'a
    'b)
b

比較関数

eq

 シンボル同士の比較
 早い

equal

 シンボル以外の比較

eql

 数値と文字を比較する(できる)

equalp

 文字の大小を区別しない、
 数値の整数、小数を区別しない、で比較する

=

 数値の比較

string-equal

 文字列の比較

char-equal

 文字の比較