kikkiiのブログ

ひきこもり

common lispで真理値表のようなもの

「命題」は英語ではpropositionと書く。数値が0のとき真の値を返す関数zeropとか、偶数かどうかを判定する関数evenpとか、奇数かとうかを判定する関数oddpとか、そういうcommon lispの関数名末尾のpは多分、propositionの頭文字pからきている。

命題は真か偽の値を持つ。common lispでは真の値をT、偽の値を()とかNILで表現する。common lispで簡単な命題を3つ書いてみる。

(defun p1 (n) (= 0 (mod n 2)))
(defun p2 (n) (= 0 (mod n 3)))
(defun p3 (n) (= 0 (mod n 5)))

p1は2で割って余りが0なら真の値を返す命題、p2は3で割って余り0のとき真の命題、p3は5で割って余り0のとき真の命題、というつもりで書いた。

optimaというパターンマッチライブラリを使えば、真理値表のようなのもが書ける。

(ql:quickload :optima)
(use-package :optima)

(defun ppp (n)
  (match (list (p1 n) (p1 n) (p3 n))
    ('(T  T  T ) " p1 ∧ p2 ∧ p3")
    ('(T  T  ()) " p1 ∧ p2 ∧¬p3")
    ('(T  () T ) " p1 ∧¬p2 ∧ p3")
    ('(T  () ()) " p1 ∧¬p2 ∧¬p3")
    ('(() T  T ) "¬p1 ∧ p2 ∧ p3")
    ('(() T  ()) "¬p1 ∧ p2 ∧¬p3")
    ('(() () T ) "¬p1 ∧¬p2 ∧ p3")
    ('(() () ()) "¬p1 ∧¬p2 ∧¬p3")))

;; 使ってみる
> (ppp 2)
" p1 ∧¬p2 ∧¬p3"

> (ppp 3)
"¬p1 ∧ p2 ∧¬p3"

> (ppp 5)
"¬p1 ∧¬p2 ∧ p3"

> (ppp 7)
"¬p1 ∧¬p2 ∧¬p3"

> (ppp (* 2 3 5))
" p1 ∧ p2 ∧ p3"

> (ppp (* 2 3 5 7))
" p1 ∧ p2 ∧ p3"

> (ppp (* 2 3))
" p1 ∧ p2 ∧¬p3"

> (ppp (* 3 5))
"¬p1 ∧ p2 ∧ p3"

> (ppp (* 2 5))
" p1 ∧¬p2 ∧ p3"

optimaを使っての、この条件分岐のやり方なかなかいいな」と思ったので記した。