次へ 前へ 目次へ 佐々木将人の個人ページへ
6 述語関数
述語関数とは,値を真か偽で返す関数です。
日本の情報処理技術者試験では,仮想機械の機械語に対応するアセンブラを使ったプログラミング問題が出題されています。このアセンブラとしてかつてはCASLという仮想アセンブラが使われていました(特定の機械やアセンブラから出題するのは不公平だと考えられていたことによります)。このCASLの命令体系はきわめて整理されており,記憶装置からCPUへのデータの転送(loadとstore),各種演算(加算・減算・論理演算・ビット操作),条件によるもしくは無条件での分岐,それにスタック操作(pushとpop)とサブルーチンへの分岐と復帰からできていました。スタック操作とサブルーチンの操作は,各種演算と分岐で表現できますので,結局CASLの,ひいてはCASLが想定する仮想機械COMETの機械語は,「(何もなければ)順次・逐次実行する」「(条件・無条件で)実行箇所を変更する」という制御構造で動いているのです。
条件付きで実行箇所を変更する,言い換えれば条件の判定をすることは,機械語・アセンブラの基本機能であり必須ということになります。
述語関数は,値を真か偽かで返す関数ですから,条件判定に用いられる典型的な関数と言えます。
もっとも,述語関数だけが条件判定に用いられるわけではありません。伝統的なLispでは,真の場合は T(もしくは t )を,偽の場合は NIL(もしくは nil )を返します。schemeでは,真の場合は #t を,偽の場合は #f を返します。しかし,Lispでは条件判定の時に「偽でないものは全て真である」という世界観を採用していますので,条件分岐は「真か偽か」というのは正確さに欠け,「偽かそうでないか」というのがより正確な表現ということになります。
※なお,伝統的なLispでは偽は nil で「 nil でないものは全て真」なのですが,schemeでは偽が #f で「 #f でないものは全て真」となる結果,「 nil は(伝統的なLispとは反対に)真」となることに注意が必要です。
Erlangにも,条件が成立する場合に(アトムの)trueを,不成立の場合に(アトムの)falseを返す関数はあります。しかし,どちらもあくまでアトムを返すのであってアトムの値はそれ自体ですから,それ以上に真偽値を示すとか論理演算の値として使用できるということはありません。
とはいえ値がないにせよ,trueを真の意味で,falseを偽の意味で使っている限り,「単なるアトムであって値を持たない」ことは気にしなくてもよいでしょう。
Lispでデータ型を調べるもの
※述語関数には末尾にpを付けるのが習慣ですが,例外もあります。
- atom
- アトムであれば真を返す。(atompではありません。)
- listp
- リストであれば真を返す
- numberp
- 数値であれば真を返す
※そのほかのデータ型を調べる述語関数としては,integerp,floatp,symbolp,stringp,conspがあります。
Lispで真偽値を反転するもの
- not
- 引数となる述語関数が偽を返した場合は真を,偽以外を返した場合は偽を返します。
Lispで数値の大小関係を調べるもの
引数としては3個以上をとることができます。その場合,全てについて大小関係が成立するとt(真)を返し,そうでなければnil(偽)を返します。
- =
- 数値として全ての引数が等しい場合に真を返します。なお = の取り扱いについては,後述の「いくつかの=」も参照すること。
- /=
- 引数が全て数値として等しくないのであれば真を返します。等しいものが1組でもあれば偽を返します。( (not (= A B C)) と (/= A B C) とは必ずしも一致しないこととなります。)
- <
- <が引数の全てについて成立すると真を返します。例えばA=1,B=2,C=3の時 (< A B C) は,A<B,B<Cがいずれも成立するので真を返します。一方A=1,B=3,C=2の時,A<Bは成立しますが,B<Cは成立しないので偽を返します。
- <=
- <か=が引数の全てについて成立すると真を返します。
- >
- >が引数の全てについて成立すると真を返します。
- >=
- >か=が引数の全てについて成立すると真を返します。
Erlangで数値の大小関係を調べる演算子
Lispとは違って,数学のよく見る記法と一緒で,比較対象の前後に演算子を入れるので,必然的に前後の数値の大小関係を調べることとなります。
- =:=
- 数値の型(整数か浮動小数点数か)が同じ,かつ,数値としても等しい場合にtrueを返します。数値の型が異なればfalse,数値の型が同じでも値が違えばfalseです。
- =/=
- 数値の型が違えばtrue,数値の型が同じでも値が違えばtrueです。=:= の裏返しです。
- ==
- 数値の型を無視して数値として等しい場合にtrueを返します。数値が等しければ型が違ってもtrueなので,数値自体が異なる場合がfalseです。
- /=
- 数値の型を無視して数値として異なる場合にtrueを返します。数値が等しければfalseです。言語によっては「<>」としていますので要注意。
- <
- 数値の型を無視して<が成立するとtrueを,そうでなければfalseを返します。
- =<
- 数値の型を無視して<か=が成立するとtrueを,そうでなければfalseを返します。他の言語ではよく「<=」と表記されますが,Erlangでは違うので注意が必要です。
- >
- 数値の型を無視して>が成立するとtrueを,そうでなければfalseを返します。
- >=
- 数値の型を無視して>か=が成立するとtrueを,そうでなければfalseを返します。
Lispにおけるいくつかの=
- eq
- Lispの内部構造的に同一のデータを指すのであれば真を返します。
文字アトムについては,同じものを複数は作らない=同じ文字アトムは必ず同一のデータを指すというのが古典的なLispの姿勢でしたので,同一の文字アトムはeqについて必ず真を返します。
一方数値アトムについては,そのような取扱をしない=数値が同じでも先行してその数値を持っているかどうかを調べることはしないので,同一の数値アトムが別々の場所に複数保管されることはあるので,同じ数値でもeqとして真を返すという保証はありません。
- =
- 数値として等しければ真を返します。数値でないものを引数にした場合はsbclではエラーになります。
その他に,eql,equal,equalpがあります。
(2023.5.30. 初版)
(2023.6.10. 改訂)
次へ 前へ 目次へ 佐々木将人の個人ページへ