忍者ブログ
数多のプログラミングを極めようとせんとする漢のブログ

prev>>Lispの文字出力| HOME |next>>Lispの再帰関数

Lispの真偽判定

比較演算子を使ってみよう

比較演算子とは2つの対象の関係性を調べるものです。具体的には"<","=",">"などです。使い方は関数と一緒で

"(< 引数1 引数2)"
"(= 引数1 引数2)"
"(> 引数1 引数2)"

などと記述します。また、これらは真の場合"T"、偽の場合"NIL"を返します。

****
; [1]> (< 1 2)
; T
; [2]> (< 2 1)
; NIL
; [3]> (< 1 1)
; NIL
; [4]> (> 2 1)
; T
; [5]> (> 1 2)
; NIL
; [6]> (= 2 1)
; NIL
; [7]> (= 2 2)
; T
****

"(< 1 2)"を見てみると、1は2より小さいのでこの場合はT(真)を返しています。次に"(< 2 1)"を見てみると、1は2より大きくないのでNIL(偽)を返しています。">"は"<"の逆関係、"="は同値関係を調べるときに使われます。また、文字列の同値関係も調べたい場合は次のequal関数を使います。

"(equal 引数1 引数2)"

****
; [1]> (equal 'abc 'def)
; NIL
; [2]> (equal 'abc 'abc)
; T
; [3]> (equal 2 2)
; T
; [4]> (equal 2 3)
; NIL
; [5]> (equal 'abc 3)
; NIL
****

論理演算子を使ってみよう

論理演算子とは真(True)か偽(False)の値しかもたないデータの演算のことをいいます。具体的には"not","and","or"などです。使い方は

"(not 引数)"
"(and 引数1 引数2 ...)"
"(or 引数1 引数2 ...)"

などと記述します。論理演算子も返り値は"T"または"NIL"になります。

****
; [1]> (and (< 1 2) (< 3 4) (< 5 6))
; T
; [2]> (and (< 1 2) (< 3 4) (> 5 6))
; NIL
; [3]> (or (< 1 2) (< 3 4) (> 5 6))
; T
; [4]> (or (> 1 2) (> 3 4) (> 5 6))
; NIL
; [5]> (not (or (> 1 2) (> 3 4) (> 5 6)))
; T
****

and関数は引数が全て真であれば真を返り値として返すものです。"(and (< 1 2) (< 3 4) (< 5 6))"では、引数の値が全て真になるので真を返します。ところが、下の"(and (< 1 2) (< 3 4) (> 5 6))"では第3引数である"(> 5 6)"の値が偽となるので偽を返します。

or関数は引数がひとつでも真であれば真を返り値として返すものです。"(or (< 1 2) (< 3 4) (> 5 6))"では第1引数と第2引数が真であるので真を返します。ところが、下の"(or (> 1 2) (> 3 4) (> 5 6))"では全ての引数が偽となるので偽を返します。

not関数は引数が真であれば偽を返し、偽であれば真を返すものです。"(or (> 1 2) (> 3 4) (> 5 6))"は偽でしたのでnot関数で囲うと真を返します。

条件分岐を使ってみよう

Lispには分岐を制御するcond関数とif関数が用意されています。

"(cond (条件1 手続き1) (条件2 手続き2) ...)"
"(if 条件 手続き 条件に当てはまらないときの手続き)"

cond関数は条件をいくつでも記述することができ、条件1から順番に調べていきます。条件が真になり次第その手続きを行います。

****
(defun absolute (x)
           (cond ((< x 0) (- 0 x))
                     ((= x 0) 0)
                     ((> x 0) x)))
; [1]> (absolute 3)
; 3
; [2]> (absolute 0)
; 0
; [3]> (absolute -3)
; 3
****

3を入力した場合で考えてみましょう。absolute関数では初めの条件として"(< x 0)"が記述されています。それは入力した数値が0よりも小さければ真を返すという意味なので偽を返します。続いて"(= x 0)"では0であれば真を返すという意味なのでここでも偽を返します。最後の"(> x 0)"では入力した数値が0よりも大きければ真を返すという意味なので真を返してそこの手続きを行います。手続きでは入力した数値をそのまま返すというものなので3が表示されました。

cond関数のよいところは条件をいくつでも記述ができることです。しかし、全ての条件に当てはまらないときは動作が保障されなくなってしまいます。それを防ぐ方法として最後の条件は必ず真になるようにします。つまり、条件を"T"とあらかじめ記述しておくのです。先ほどのabsolute関数では条件に当てはまらないということはないのですが、このように記述する癖をつけることで他の関数を定義するときに、条件がひとつも当てはまらなくなってしまうものがあるという可能性を事前に回避することができます。

****
(defun absolute (x)
           (cond ((< x 0) (- 0 x))
                     ((= x 0) 0)
                     (T x)))
****

if関数はcond関数とは違い条件をひとつしか記述することができませんが、手続きのなかにif関数を記述するとcond関数のように扱うこともできます。

****
(defun renum (x)
           (if (< x 0)
               (if (= x -3) 1 2)
               0))
; [1]> (absolute2 -3)
; 1
; [2]> (absolute2 -2)
; 2
; [3]> (absolute2 0)
; 0
****

演習
if関数を用いて引数の絶対値を返す関数absolute2を定義せよ。
上の関数absoluteと同様に正数、0、負数の順で評価せよ。










演習解答
****
(defun absolute2 (x)
           (if (< x 0)
               (- 0 x)
               x))
; [1]> (absolute2 3)
; 3
; [2]> (absolute2 0)
; 0
; [3]> (absolute2 -3)
; 3
****

拍手[1回]

PR

prev>>Lispの文字出力| HOME |next>>Lispの再帰関数