X 3012 : 1998(ISO/IES 13816 : 1997
(1)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
まえがき
この規格は,工業標準化法に基づいて,日本工業標準調査会の審議を経て,通商産業大臣が制定した日
本工業規格である。
X 3012 : 1998(ISO/IES 13816 : 1997
(1)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
目次
ページ
序文 ··································································································································· 1
1. 適用範囲,表記法及び適合性 ····························································································· 1
1.1 適用範囲 ······················································································································ 1
1.2 引用規格 ······················································································································ 1
1.3 表記法 ························································································································· 1
1.4 字句要素 ······················································································································ 3
1.4.1 分離記号 ···················································································································· 4
1.4.2 注釈 ·························································································································· 4
1.5 テキスト表現 ················································································································ 4
1.6 予約語 ························································································································· 5
1.7 定義 ···························································································································· 5
1.8 エラー ························································································································· 7
1.8.1 エラー指定 ················································································································· 7
1.8.2 広範囲に使われるエラー ······························································································· 8
1.9 ISLISPプロセッサ及びISLISPテキストの適合性 ·································································· 8
2. クラス ··························································································································· 8
2.1 メタクラス ··················································································································· 9
2.2 定義済みクラス ············································································································ 10
2.3 標準クラス ·················································································································· 11
2.3.1 スロット ··················································································································· 11
2.3.2 クラスのインスタンスの生成 ························································································ 12
3. 有効範囲及び存在期間 ····································································································· 12
3.1 静的原理 ····················································································································· 12
3.2 識別子の有効範囲 ········································································································· 13
3.3 個別の有効範囲規則 ······································································································ 13
3.4 存在期間 ····················································································································· 13
4. 評価形式及び評価 ··········································································································· 14
4.1 評価形式 ····················································································································· 14
4.2 関数適用形式 ··············································································································· 15
4.3 特殊形式 ····················································································································· 15
4.4 定義形式 ····················································································································· 15
4.5 マクロ形式 ·················································································································· 16
4.6 評価モデル ·················································································································· 16
4.7 関数 ··························································································································· 16
4.8 定義演算子 ·················································································································· 19
X 3012 : 1998 (ISO/IEC 13816 : 1997) 目次
(2)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
5. 述語 ····························································································································· 20
5.1 真偽値 ························································································································ 20
5.2 クラス述語 ·················································································································· 21
5.3 等価性 ························································································································ 21
5.4 論理演算 ····················································································································· 23
6. 制御構造 ······················································································································· 25
6.1 定数 ··························································································································· 25
6.2 変数 ··························································································································· 25
6.3 動的変数 ····················································································································· 28
6.4 条件式 ························································································································ 29
6.5 評価形式の逐次実行 ······································································································ 31
6.6 繰返し ························································································································ 31
6.7 非局所的脱出 ··············································································································· 32
6.7.1 非局所的脱出の設定及び起動 ························································································ 32
6.7.2 非局所的脱出におけるデータ整合性の保証 ······································································ 36
7. オブジェクト指向機能 ····································································································· 37
7.1 クラスの定義 ··············································································································· 37
7.1.1 クラス優先度リストの決定 ··························································································· 40
7.1.2 スロットのアクセス ···································································································· 40
7.1.3 スロット及びスロット任意機能の継承 ············································································ 41
7.2 包括関数 ····················································································································· 41
7.2.1 包括関数の定義 ·········································································································· 42
7.2.2 包括関数に対するメソッド定義 ····················································································· 43
7.2.2.1 パラメタ特殊化指定及び修飾子に関する合致 ································································ 44
7.2.2.2 包括関数のラムダリストとメソッドのパラメタ記述との合同 ··········································· 44
7.2.3 メソッドの継承 ·········································································································· 44
7.3 包括関数の呼出し ········································································································· 44
7.3.1 適用可能なメソッドの選択 ··························································································· 44
7.3.2 適用可能メソッドの優先順位 ························································································ 45
7.3.3 メソッドの適用 ·········································································································· 45
7.3.3.1 単純メソッド組合せ ································································································· 45
7.3.3.2 標準メソッド組合せ ································································································· 45
7.3.4 次メソッド及びその呼出し ··························································································· 47
7.4 オブジェクトの生成及び初期化 ························································································ 47
7.4.1 インスタンスの初期化 ································································································· 47
7.5 クラスに関する問合せ···································································································· 48
8. マクロ ·························································································································· 49
9. 宣言及び型変換 ·············································································································· 50
10. 記号クラス ·················································································································· 51
10.1 記号名 ······················································································································· 52
X 3012 : 1998 (ISO/IEC 13816 : 1997) 目次
(3)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
10.1.1 記号の表記 ··············································································································· 52
10.1.2 記号名における大小文字 ····························································································· 52
10.1.3 nil及び() ·············································································································· 53
10.2 記号属性 ···················································································································· 53
10.3 名前なしの記号 ··········································································································· 53
11. 数値クラス··················································································································· 54
11.1 数値クラス ················································································································· 54
11.2 浮動小数点数クラス ····································································································· 60
11.3 整数クラス ················································································································· 62
12. 文字クラス ·················································································································· 64
13. リストクラス ··············································································································· 66
13.1 コンス ······················································································································· 66
13.2 空リストクラス ··········································································································· 67
13.3 リスト操作 ················································································································· 68
14. 配列 ··························································································································· 71
14.1 配列のクラス ·············································································································· 71
14.2 一般配列 ···················································································································· 72
14.3 配列操作 ···················································································································· 72
15. ベクタ ························································································································ 74
16. 文字列クラス ··············································································································· 75
17. 列 ······························································································································ 77
18. ストリームクラス ········································································································· 79
18.1 ファイルへのストリーム ······························································································· 81
18.2 その他のストリーム ····································································································· 82
19. 入出力 ························································································································ 83
19.1 入力関数の引数についての共通事項 ················································································ 83
19.2 文字入出力 ················································································································· 83
19.3 2進入出力 ·················································································································· 87
20. ファイル ····················································································································· 88
21. 例外処理機能 ··············································································································· 89
21.1 例外状態 ···················································································································· 89
21.2 例外状態の通知及び扱い ······························································································· 89
21.2.1 例外通知に関する操作 ································································································ 90
21.2.2 例外処理に関する操作 ································································································ 91
21.3 例外オブジェクトに付随するデータ ················································································ 91
21.3.1 算術エラー ··············································································································· 91
21.3.2 定義域エラー ············································································································ 92
21.3.3 構文解析エラー ········································································································· 92
21.3.4 単純なエラー ············································································································ 92
21.3.5 ストリームエラー ······································································································ 92
X 3012 : 1998 (ISO/IEC 13816 : 1997) 目次
(4)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
21.3.6 未定義実体のエラー ··································································································· 93
21.4 エラー名 ···················································································································· 93
22. その他の機能 ··············································································································· 95
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
日本工業規格 JIS
X 3012 : 1998
(ISO/IEC 13816 : 1997)
プログラム言語ISLISP
Information technology−Programming languages, their
environments and system software interfaces−
Programming language ISLISP
序文 この規格は,1997年に第1版として発行されたISO/IEC 13816, Information technology−Programming
languages, their environments and system software interfaces−Programming language ISLISPを翻訳し,技術的内
容を変更することなく作成した日本工業規格である。
なお,この規格で側線を施してある“参考”は,原国際規格にはない事項である。
1. 適用範囲,表記法及び適合性
1.1
適用範囲
a) 適用事項 この規格は,ISLISPプロセッサ及びISLISPテキストに対する適合性要件を規定し,プロ
グラム言語ISLISPの構文及び意味を規定する。
b) 適用外事項 この規格は,次の事項を規定しない。
1) 特定のデータ処理システムの能力又はプロセッサの能力を超えるISLISPテキストの大きさ又は複
雑さ,及び能力を超えた場合にとる動作。
2) ISLISPプロセッサを実装できるデータ処理システムの最小要件。
3) ISLISPテキストを実行準備する方法,及び実行のために準備されたISLISPテキストを起動する方
法。
4) 人が読むために刊行されるISLISPテキストの印刷上の表示。
5) 処理系が提供するかもしれない又は提供しないかもしれない拡張機能。
備考 この規格の対応国際規格を,次に示す。
ISO/IEC 13816 : 1997, Information technology−Programming languages, their environments and
system software interfaces−Programming language ISLISP
1.2
引用規格 次に掲げる規格は,この規格に引用されることによって,この規格の一部を構成する。
この規格の制定時点では,次の規格が最新規格であるが,改正されることもあるので,この規格を使う当
事者は,最新版を適用できるかどうかを検討するのが望ましい。
・ISO/IEC TR 10034 : 1990, Guidelines for the preparation of conformity clauses in programming
language standards
・IEEE standard 754-1985, Standard for binary floating-point arithmetic
1.3
表記法 構文の概念及び意味の概念を明確に定義し,かつ,これらの概念を区別するために,この
規格では複数の記述抽象化のレベルを用いる。
2
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
ISLISPテキストの構成単位から,ISLISPデータ構造の表現への対応が存在する。この規格では,テキス
トと,それに対応するISLISPオブジェクト(データ構造)とを,同時に取り扱う。ISLISPのテキストは,
ISLISPのデータ構造の外部仕様とみなすことができる。これらの二つの表現を区別するために,異なる概
念を使用する。テキスト表現の場合は,テキストの構成要素(識別子,リテラル,複合形式など)を使用
する。一方,ISLISPのオブジェクトの場合は,オブジェクト(記号,リストなど)を使用する。
ISLISPテキストの構成要素を評価形式 (evaluation form) 又は単に形式 (form) と呼ぶ。評価形式は,識
別子,リテラル又は複合形式とする。複合形式は,関数適用形式,マクロ形式,特殊形式又は定義形式と
する。
識別子は,記号によって表現する。複合形式は,空でないリストによって表現する。リテラルは,記号
及びリストのいずれでも表現できない。したがって,リテラルは,識別子及び複合形式のいずれでもない。
例えば,数値はリテラルである。
オブジェクトは,実行のために準備される (prepared for execution)。これは,プログラム変換又はコンパ
イルを意味し,マクロ展開を含む。この規格は,検出しなければならない違反を定義するが,実行準備の
方法及びその結果は定義しない。実行準備が成功した場合は,その結果は,実行 (execution) 可能な状態
となる。実行準備及びそれに続く評価がISLISPの評価モデル (evaluation model) を実装する。ここで,“評
価”という用語を用いる理由は,ISLISPが式言語であるためである。すなわち,各評価形式は値をもち,
その評価形式を含む評価形式の値を計算するために使われる。この規格では,ある実体が実行のために準
備された結果を,“実行準備された実体”と表すことがある。例えば,“実行準備された評価形式”,“実行
準備された特殊形式”などと表す。
例 “cond特殊形式”は,実行のために準備されて“実行準備されたcond”となる。
実行例におけるメタ記号“⇒”は,実際の評価の結果を示す。例えば,
(+ 3 4) ⇒7
メタ記号“→”は,与えられたパターンをもつ評価形式を評価した際の,結果のクラスを示す。例えば,
(+ i1 i2) →<integer>
評価形式のパターン(通常は,関数名又は特殊演算子である定数部分によって定義される。)に対しては,
そのパターンに一致するすべての評価形式を評価した結果が属するクラスを“→”で示す。
同値な評価形式のパターン又は評価形式を,“≡”によって関係付ける。
評価形式のパターンに関しては,次の表記法を使用する。
(f-name argument*) →結果のクラス
f kind
この表記法では,イタリック体の単語は,非終端記号(パターン変数)を表す。f-nameは,常に終端記
号であり,特定の関数名,特殊演算子,定義演算子又は包括関数名のいずれかとする。
この表記法で下線を付けた用語(例えば,定義形式におけるname)は,評価されない式であることを意
味する。評価形式が評価される場合とされない場合があるとき(例えば,ifにおけるthen-form及びeles-
form)は,そのことを規定に明記する。
クラス名は,一律に<class-name>と表記する。例えば,<list>は,通常“リストクラス”と呼ばれるクラ
スの名前である。
パターン変数に関しては,次の表記法を用いる。
term+ termが一つ以上現れることを意味する。
term* termが0個以上現れることを意味する。
3
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
[term] termが高々一つしか現れないことを意味する。すなわち,termが省略可能で
あることを意味する。
{term1 term2...} 各termをまとめることを意味する。
term1|term2|... いずれかのtermが一つだけ現れることを意味する。
評価形式の引数がクラスの制約をもつ場合は,その評価形式を規定するために次の名前を使用する。
array, array1,...arrayj,...
<basic-array>
cons, cons1,...consj,...
<cons>
list, list1,...listj,...
<list>
obj, obj1,...objj,...
<object>
sequence, sequence1,...sequencej,...
<basic-vector>又は<list>(17.参照)
stream, stream1,...streamj,...
<stream>
string, string1,...stringj,...
<string>
char, char1, charj,...
<character>
function, function1,...functionj,...
<function>
class, class1,...classj,...
<class>
symbol, symbol1,...symbolj,...
<symbol>
x, x1,...xj,...
<number>
z, z1,...zj,...
<integer>
この規格では,特にことわらない限り,次の方式を使用する。
-p
述語(“真偽値関数”と呼ばれることがある)の名前は,通常-pで終わる。通常,すべて
のクラス<name>は特性関数をもつ。特性関数の名前は,nameがハイフンを含む場合は
name-p(例えば,generic-function-p)とし,ハイフンを含まない場合はnamep(例えば,
symbolp)とする。ただし,名前が “p” で終わる関数のすべてが述語とは限らない。
create-
通常,組込みクラス<name>は生成関数をもち,その名前はcreate-nameとする。
def
これは,定義演算子の接頭語として使用する。
set-
この規格では,set-nameという名前の関数はすべて,場所に対する書込み関数であり,name
という名前の,対応する読出し関数が存在する。
この言語におけるどのような実体に対しても,名詞句 “entity-kind name” は,nameによって表される
entity-kindという種類の実体を意味する。例えば,名詞句“関数name”,“定数name”及び“クラスname”
は,nameによって表される関数,定数及びクラスをそれぞれ意味する。
1.4
字句要素 ISLISPテキストは,字句要素によって構成する。字句要素は,次の文字によって構成す
る(12.参照)。
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 + - < > / * & = . ? ̲ ! $ % : @ [ ] ^ { } 〜 #
これ以外の文字は,処理系定義とする。
次の文字は,それ自体で字句要素とする(8.及び13.1参照)。
( ) ʻ , ʼ
次の文字の組は,それ自体で字句要素とする(4.7,8.及び14.1参照)。ここで,nは10進数の並びとす
る。
4
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
#ʼ #( , @ #B #b #O #o #X #x #nA #na
記号(10.参照),数値(11.参照),文字(12.参照)及び文字列(16.参照)は,字句要素とする。
\(単一エスケープ)及び|(多重エスケープ)は,特殊文字とする。これらは,ある種の字句要素(識
別子,文字列リテラルなど)の中に現れてもよい。
これ以外の字句要素は,区切り記号によって分離する。区切り記号は,分離記号及び次の文字とする。
( ) ʻ , ʼ
区切り記号が文字列(16.参照)の中,一対の多重エスケープ文字(10.参照)で囲まれた部分,又は#\
の直後の文字として現れた場合には,区切り記号としての効果は無効とする。
参考 JIS X 0201では,文字〜はオーバライン (7/14) に対応し,文字\は円記号 (5/12) に対応してい
る。
1.4.1
分離記号 分離記号は,空白,コメント,復帰改行及び処理系定義の文字(例えば,タブ)とする。
分離記号は意味をもたず,別の分離記号で置き換えても,ISLISPテキストの意味を変えることはない。
1.4.2
注釈 セミコロン (;) は,注釈開始 (comment begin) のための文字とする。すなわち,セミコロン
と,それに続く行末までの文字が注釈となる。
#|で始まり,|#で終わる文字の並びは注釈とする。これらの注釈を入れ子にしてもよい。
注釈は,分離記号であり,字句要素の中に現れることはできない。
1.5
テキスト表現 オブジェクトのテキスト表現は,機械独立とする。ISLISPオブジェクトのテキスト
表現の幾つかを次に示す。これらの表現は,read関数によって読み込むことができる。字句要素について
は,1.4に示す。
a) 空リスト (null) オブジェクトnilは,クラス<null>に属する唯一のオブジェクトとする。入力の際に
は,nil又は()と表記する。nil又は()のいずれが出力されるかは,処理系定義とする。
b) リスト (list) リストは,通常,nilで終わり, (obj1 obj2...objn) と表記する。ドットリスト(すなわ
ち,末尾がnilでないリスト)は, (obj1 obj2…objn.objn+1) と表記する。
c) 文字 (character) <character>クラスのインスタンスは,#\?と表記する。“?”は,この表記が表現す
る文字とする。この記法で表記されない特別な標準文字が二つある。これらは,復帰改行文字及び空
白文字であり,それぞれ#\newline及び#\spaceと表記する。
d) コンス (cons) コンスは, (car .cdr) と表記する。ここで,car及びcdrは,オブジェクトとする。
e) 整数 (integer) 整数(10進)は,10進数の並びで表現し,正符号 (+) 又は負符号 (-) で始めても
よい。2進数,8進数及び16進数は,テキスト表現をそれぞれ#b, #o及び#xで始める。
f)
浮動小数点数 (float) 浮動小数点数は,次のいずれかの形で表記する。
[s] dd...d.dd...d
[s] dd...d.dd...dE[s]dd...d
[s] dd...d.dd...de[s]dd...d
[s] dd...dE[s]dd...d
[s] dd...de[s]dd...d
ここで,sは “+” 又は “-” であり,dは “0” 〜 “9” のいずれかとする。例えば,987.12,+12.5E-13,
-1.5E12,1E32(1)。
注(1) この数値は自然数ではあるが,その表記のために,浮動小数点数とみなす。
g) ベクタ (vector) クラス <general-vector> に属するベクタは,#(obj1...objn) と表記する。
h) 配列 (array) クラス<general-array*>又はクラス<general-vector>に属する配列は,入力の際には#ra(r
5
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
は配列の次元数を表す整数)に続けて,その配列の内容を表す並びを入れ子構造にして表記する。そ
の構造は,次のように定義する。r=1のとき,配列構造は単純に (obj1...objn) とする。r>1のとき,
各次元の大きさをn1, n2,..., nrとすると,配列構造は (str1...strn1) となる。ここで,striはr−1次元の部
分配列構造であり,個々の部分配列の各次元の大きさはn2,..., nrとする。例えば, (create-array ʼ(2 3 4)
5) が生成する配列は,次のように表記する。
#3a(((5 5 5 5) (5 5 5 5) (5 5 5 5)) ((5 5 5 5) (5 5 5 5) (5 5 5 5)))
出力(format参照)に際しては,クラス<general-vector>に属する配列は,#(...) の形で出力する。
i)
文字列 (string) 文字列は一対の”で囲まれた文字の並びによって表記する。例えば, “abc”。特殊
文字の前には,逆斜線をエスケープ文字として使用する。
j)
記号 (symbol) 名前付きの記号は,その印字名で表記する。印字名が特殊文字(10.参照)を含む場
合は,印字名を囲む縦線 (|) が必要となるときがある。名前なしの記号の表記は,処理系定義とする。
オブジェクトの中には,テキスト表現をもたないものがある。例えば,クラス及び<function>クラスのイ
ンスタンスは,テキスト表現をもたない。
1.6
予約語 名前にコロン (:) 及び/又はアンパサンド (&) を含む記号は予約されており,識別子とし
て使用してはならない。名前がコロン (:) で始まる記号を,キーワード (keyword) と呼ぶ。
1.7
定義 この規格では,次の定義を用いる。
1.7.1
抽象クラス (abstract class) 定義によって,直接インスタンスをもつことが許されないクラス。
1.7.2
活動 (activation) 関数の計算。個々の活動は,起動時点,活動期間及び活動終了時点をもってい
る。活動は,関数適用形式によって起動される。
1.7.3
アクセス関数 (accessor) インスタンスのスロットに対する読出し関数と書込み関数との総称。
1.7.4
束縛 (binding) 束縛には,構文的側面と意味論的側面とがある。
構文的には,“束縛”は,識別子と,束縛するISLISP評価形式との関係を規定する。束縛されているか
どうかは,識別子が定義されている位置とそれが参照されている位置とを関係付けることによって,検査
できる。
意味論的には,“束縛”は,変数,変数名及びオブジェクトの間の関係(又は変数とその場所との関係)
を規定する。この関係は,束縛という実体によって具現化されていると考えることができる。そのような
束縛の実体は,実行時に構築され,後で破壊される。ただし,束縛によっては,無制限の存在期間をもつ
場合がある。
1.7.5
クラス (class) オブジェクトであって,インスタンスと呼ばれる一群のオブジェクトの構造及び
振る舞いを決定する。振る舞いとは,一つのインスタンスに対して実行できる操作の集合である。
1.7.6
例外状態 (condition) 実行中のプログラムによって検出される(又は検出される可能性のある)
状況を表現するオブジェクト。
1.7.7
定義位置 (definition point) ISLISPテキストのテキスト上の位置であり,その位置以降では,定
義されたオブジェクトは識別子によって表現される。
1.7.8
直接インスタンス (direct instance) ISLISPオブジェクトは,唯一のクラスの直接インスタンスで
ある。その唯一のクラスを,“そのオブジェクトのクラス”と呼ぶ。直接インスタンスは振る舞いをともな
い,直接インスタンスのすべての集合が,一つのクラスを構成する。
1.7.9
動的 (dynamic) プログラムの実行によって初めて決定でき,一般に,静的に決定することが不
可能な影響をもつ。
6
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
1.7.10 動的変数 (dynamic variable) 最も最近に束縛を設定した活性ブロックによって,その束縛が決定
される変数。静的原理によって,静的に自明なブロックによって束縛が決定されるものではない。
1.7.11 評価 (evaluation) 実行のために準備された評価形式の計算。その結果は,値及び/又は副作用
となる。
1.7.12 実行 (execution) 活動の並び。活動は入れ子になることもある。
1.7.13 拡張 (extension) この規格の要求に対する処理系定義の追加事項であり,次の条件をすべて満た
すもの。
・ 特定の識別子の使用を禁止することを除き,この規格に適合するISLISPテキストの正当性を損なわ
ない。
・ エラーを通知するようこの規格が要求している動作の集合を変更しない。
・ 処理系依存と指定されている機能の状態を変更しない。
1.7.14 評価形式 (evaluation form) プログラムテキスト中の,構文的に正しい単位であり,実行のため
に準備することが可能であるもの。
1.7.15 関数 (function) ISLISPオブジェクトであり,引数を伴って呼び出され,計算(副作用を伴って
もよい。)を行い,値を返すもの。
1.7.16 包括関数 (generic function) 関数であり,その呼出しの際の振る舞いが引数の値の属するクラス
によって決定され,一般的には複数のメソッドによって構成されるもの。
1.7.17 識別子 (identifier) ISLISPオブジェクトを指定する静的構成要素(字句要素)。ISLISPテキスト
をデータ構造で表現する場合,識別子は記号で表現する。
1.7.18 変更不可能な束縛 (immutable binding) 束縛が変更不可能であるとは,識別子とそれが表現する
オブジェクトとの関係が変更できないことを意味する。変更不可能な束縛を変更しようと試みた場合は,
違反とする(エラー名immutable-binding)。
1.7.19 変更不可能なオブジェクト (immutable object) オブジェクトが変更不可能であるとは,それが
変更できないことを意味する。変更するための演算子が用意されていない場合,及び変更を行う演算子の
使用を禁止する何らかの制約がある場合に,変更不可能となる。特にことわらない限り,適合するプロセ
ッサは,変更不可能なオブジェクトを変更する試みを検出しなくてもよい。変更不可能なオブジェクトを
変更する試みが行われた場合は,結果は未定義とする。
1.7.20 処理系定義 (implementation defined) ISLISPプロセッサごとに異なるかも知れない機能である
が,個々のプロセッサごとに完全に定義されているもの。
1.7.21 処理系依存 (implementation dependent) ISLISPプロセッサごとに異なるかも知れない機能であ
るが,個々のプロセッサによっては必ずしも定義されていないもの。
備考 適合するISLISPテキストは,処理系依存の機能に依存してはならない。
1.7.22 継承 (inheritance) クラスとその(直接又は間接の)上位クラスとの関係であり,上位クラスの
構造及び振る舞いをそのクラスに写像する関係。ISLISPは,制限された多重継承を可能とする。すなわち,
クラスは,直接の上位クラスを同時に複数もつことが可能である。
1.7.23 (クラスの)インスタンス (instance) クラスの直接インスタンス又はその下位クラスのインス
タンス。
1.7.24 リテラル (literal) プログラム中に,表現が定数として直接現れているオブジェクト。
1.7.25 メタクラス (metaclass) インスタンスがクラスであるクラス。
7
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
1.7.26 メソッド (method) 特定のパラメタ記述に対応して,包括関数の,クラスに固有な振る舞い及び
操作を定義する実体。
1.7.27 オブジェクト (object) ISLISPプロセッサが生成,破壊,操作,比較,格納,入力又は出力する
ことができるものは,すべてオブジェクトである。特に,関数はISLISPオブジェクトである。関数に引数
として渡され,値として返され,変数に束縛され,構造体の一部となり得るオブジェクトを第1級オブジ
ェクト (first-class object) と呼ぶ。
1.7.28 演算子 (operator) 複合形式の第1要素であり,その評価形式が特殊形式であることを示す予約
された名前,マクロの名前,ラムダ式又は関数の名前空間に属する識別子。
1.7.29 パラメタ記述 (parameter profile) メソッドのパラメタリストであり,それぞれのパラメタには,
そのクラス名が付随する。パラメタにクラス名が付随しない場合,そのパラメタは,最も一般的なクラス
に属する。
1.7.30 場所 (place) オブジェクトは場所に格納して,後で取り出すことができる。場所は,評価形式に
よって指定され,setfの第1引数となり得る。このように使われた場合,オブジェクトは,その場所に格
納される。評価形式がsetfの第1引数以外として使用された場合は,格納されているオブジェクトが取り
出される。場所として許される評価形式の一覧を,setfの規定で示す。
1.7.31 位置 (position)
a) 引数位置 評価形式の第1要素以外の要素が現れる位置。
b) 演算子位置 評価形式の第1要素が現れる位置。
1.7.32 処理 (process) 実行準備されたISLISPテキストの実行。
1.7.33 プロセッサ (processor) ISLISPテキスト(又はそれと等価なデータ構造)を入力として受け入れ,
それを実行のために準備し,結果を実行して値と副作用とを生成するシステム又は機構。
1.7.34 プログラム (program) 評価する式の集合体であり,その特性は文脈に依存する。この規格では,
“プログラム”という用語は,抽象的にだけ使用する。すなわち,プログラムに対する特定の構文は存在
しない。
1.7.35 有効範囲 (scope) 識別子の有効範囲とは,その識別子の意味が定義されているテキスト部分。す
なわち,その識別子が指し示すISLISPオブジェクトが存在するテキスト部分。
1.7.36 スロット (slot) インスタンスの名前付きの構成要素であり,スロットアクセスメソッドを使っ
てアクセスできるもの。インスタンスの構造は,そのスロットの集合によって定義される。
1.7.37 テキスト (text) この規格の要求に適合する(すなわち,ISLISPの構文及び静的意味を有する)
テキスト。ISLISPテキストは,最上位形式の並びによって構成する。
1.7.38 最上位形式 (toplevel form) 他の評価形式の中に入れ子になっていない評価形式又はprogn形式
の中にだけ入れ子になっている評価形式。
1.7.39 最上位有効範囲 (toplevel scope) 完全なISLISPテキストの単位が処理される有効範囲。
1.7.40 書込み関数 (writer) クラスのインスタンスのスロットに値を束縛する役割を担う包括関数。
1.8
エラー エラー (error) とは,実行中に起きる状況であり,この規格が定義する意味に従ってプロセ
ッサが正しい実行を続けることが不可能な状況とする。このようなエラーを検出して報告する行動を,エ
ラーを通知する (signal) と呼ぶ。
違反 (violation) とは,実行準備の際に起こる状況であり,この規格が規定するテキスト上の要求が満た
されなかった状況とする。違反は,実行準備の際に検出される。
1.8.1
エラー指定 この規格におけるエラー指定の用語を次に示す。
8
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
a) エラーが発生する 処理系は,この種のエラーを,そのエラーを含む評価形式の実行完了以前,でき
る限り早期(例えば,そのコードが実行のために準備されるとき)に検出しなければならない。
処理系は,現在の評価形式の評価を停止しなければならない。実行中の処理全体を終了するのか,
デバッガに入るのか,又は制御をその処理の他の場所に移行するのかは,処理系定義とする。ただし,
利用者がハンドラを設定している場合は,この限りではない。
b) 結果は未定義とする これは,結果が予測不能であることを意味する。結果は,無害なものから,致
命的なものまでさまざまである。適合するISLISPテキストは,その結果及び影響に依存してはならな
い。適合するISLISPテキストは,その結果を予測不能として取り扱わなければならない。この規格で
結果を明示していない要求事項又は禁止事項に反した場合,結果は未定義とする。処理系は,この場
合にエラーを通知してもよい。
索引及び相互参照を簡単にするために,この規格におけるエラーには,エラー名を付け,“(エラー
名sample)”と表記する。これらのエラー名は,ISLISPテキスト及びISLISPプロセッサに対して,意
味論的な重要性をもたない。処理系がエラーを表現するためのオブジェクトのクラス,及び表示する
エラーメッセージの文章は処理系依存とする。
1.8.2
広範囲に使われるエラー 大多数のエラーについては,それらが現れる文脈で詳細に規定する。幾
つかのエラーは,広範囲に使われるものであり,ここで規定する。
a) 定義域エラー クラスの制約を有する標準関数の引数として与えられたオブジェクトが,関数が要求
するクラスのインスタンスでない場合は,エラーが発生する(エラー名domain-error)。
b) パラメタ数エラー 関数が要求するパラメタの個数と異なる個数の引数を伴って,その関数が起動さ
れた場合は,エラーが発生する(エラー名arity-error)。
c) 未定義エラー 識別子によって指し示される実体が,その実体を参照するときに未定義である場合は,
エラーが発生する(エラー名undefined-entity)。この種類のエラーで頻度の高いものに,
undefined-function及びunbound-variableがある。
これらが,すべての種類のエラーではない。より完全な一覧を,21.4に示す。
1.9 ISLISPプロセッサ及びISLISPテキストの適合性 この規格の要求に適合するISLISPプロセッサは,
次の項目を満たさなければならない。
a) この規格が規定するすべての機能を受け入れ,実装する。
b) 違反(1.8参照)であるとこの規格が明記する事項を含むテキストを拒絶する。
c) この規格で処理系定義と規定した機能をすべて定義する文書を備えている。
d) プロセッサが受け入れる機能で,この規格が規定していないものを定めた文書を備えている。これら
の拡張は,“JIS X 3012 : 1998が規定するISLISPの拡張である”と明記しなければならない。
適合するISLISPテキストは,処理系依存機能に依存してはならない。しかし,適合するISLISPテキス
トは,この規格が要求する処理系定義機能に依存してもよい。
適合するISLISPテキストは,この規格が定義する名前付き定数に対する局所的な変数束縛を行ってはな
らない。そのような試みが行われた場合は,違反とする。
2. クラス ISLISPにおいて,データ型は,クラスシステムとして実現する。クラス (class) は,それ自
身一つのオブジェクトであり,他のオブジェクトの集合の構造及び振る舞いを決定する。この集合の個々
のオブジェクトを,インスタンス (instance) と呼ぶ。どのISLISPオブジェクトも,あるクラスのインスタ
ンスとする。振る舞いとは,インスタンスに対して行い得る操作の集合とする。
9
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
クラスは,他のクラスから構造及び振る舞いを継承できる。他のクラスからの継承を目的に,クラス定
義の中でそれらのクラスを参照するクラスを,それらのクラスの下位クラス (subclass) と呼ぶ。継承の目
的で指定したクラスを,継承しているクラスの上位クラス (superclass) と呼ぶ。
一つのクラスは一つの識別子を名前としてもつ。この識別子は,例えば,メソッドの定義において,パ
ラメタ特殊化指定として使うことができる。ある名前に対応するクラスオブジェクトを参照するには,特
殊形式のclassを使用する。
C2というクラスの定義の中で,明示的にC1を上位クラスとして指定している場合,又はこの規格の中
で指定している場合(例えば,図1において,C2がC1から矢印で結ばれている場合),クラスC1は,クラ
スC2の直接の上位クラス (direct superclass) という。このとき,C2はC1の直接の下位クラス (direct subclass)
という。クラスの並びC1, ..., Cnが存在し,1<i<nであるすべてのiに対して,CiがCi+1の直接の上位ク
ラスである場合,クラスC1をCnの上位クラス (superclass) という。この場合,CnはC1の下位クラス
(subclass) という。どのクラスも,自分自身の上位クラスではなく,自分自身の下位クラスでもない。すな
わち,C1がC2の上位クラスの場合,C1とC2とは同じクラスではない。あるクラスC及びCのすべての上
位クラスからなる集合を,“C及びその上位クラス”という。
利用者定義のクラスCが二つのクラスC1及びC2を継承している場合,C1及びC2に共通の上位クラス
は,<standard-object>及び<object>に限る。これによって,制限された多重継承が許される。
どのISLISPオブジェクトも,唯一のクラスの直接インスタンスとする。その唯一のクラスを,“そのオ
ブジェクトのクラス”と呼ぶ。
クラスのインスタンスとは,そのクラスの直接インスタンスであるか,又はそのクラスの下位クラスの
インスタンスとする。
クラスは,上位下位の関係によって循環のない有向グラフ (directed acyclic graph) を構成する。このグラ
フの節はクラスを表し,C2がC1の直接の下位クラスであるときにだけ,C1からC2に有向辺が存在する。
このグラフを継承グラフ (inheritance graph) と呼ぶ。継承グラフは<object>というクラスを根とし,これは,
上位クラスをもたない唯一のクラスとする。それゆえ,<object>は,自分以外のすべてのクラスの上位ク
ラスとなる。<standard-object>という名前のクラスは,<standard-class>というクラスのインスタンスとする。
<standard-object>は,<standard-class>のインスタンスであるすべてのクラス(ただし,<standard-object>
自身は除く。)の上位クラスとする。
それぞれのクラスには,クラス優先度リスト (class precedence list) がある。これは,与えられたクラス
及びそのすべての上位クラスの間の全順序関係を表す。この全順序関係は,最も優先度の高いクラスから,
最も優先度の低いクラスへの順にクラスを並べたものとする。クラス優先度リストは,幾つかの方法で利
用する。一般に,クラスはその上位クラスの特性を継承するが,より優先度の高いクラスは,それらの特
性を遮へいする (shadow),すなわち上書きすることができる。また,メソッドを選択したり結合する処理
においては,メソッド間の優先順序を決定するために,クラス優先度リストが利用される。
2.1
メタクラス クラスは,それ自身があるクラスのインスタンスであるオブジェクトとして表現され
る。あるオブジェクトのクラスのクラスを,そのオブジェクトのメタクラス (metaclass) と呼ぶ。メタク
ラスという用語は,クラスをインスタンスとしてもつクラスを指すために使用する。
メタクラスは,そのインスタンスであるクラスに関する継承の方法を決定し,そのクラスのインスタン
スの表現を決定する。
ISLISPのオブジェクトシステムでは,次のものを定義済みのメタクラスとする。
・ <standard-class>は,特に指定のないとき,defclassで定義されるクラスのクラスとする。
10
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
・ <built-in-class>は,特別な実装をもつか,又は機能に制限をもつクラスをインスタンスとするクラスと
する。例えば,<built-in-class>のインスタンスであるクラスに対しては,下位クラスを定義してはなら
ない。
2.2
定義済みクラス 次のクラスは,クラスシステムにおける基本クラス(すなわち,メタクラス以外
の定義済みのクラス)とする。
<arithmetic-error>
<floating-point-underflow>
<simple-error>
<basic-array>
<function>
<standard-generic-function>
<basic-array*>
<general-array*>
<standard-object>
<basic-vector>
<general-vector>
<storage-exhausted>
<character>
<generic-function>
<stream>
<cons>
<integer>
<stream-error>
<control-error>
<list>
<string>
<division-by-zero>
<null>
<symbol>
<domain-error>
<number>
<unbound-variable>
<end-of-stream>
<object>
<undefined-entity>
<error>
<parse-error>
<undefined-function>
<float>
<program-error>
<floating-point-overflow>
<serious-condition>
<standard-class>及び<built-in-class>は,定義済みのメタクラスとする。
利用者がdefclassで定義したクラスは,<standard-class>のインスタンスとなる。定義済みのクラスは,
あたかもdefclassで定義されたかのように<standard-class>のインスタンスとして実装するか又は
<built-in-class>のインスタンスとして実装するかのいずれかとする。
図1に,ISLISPで定義されるクラス間に定められた継承関係を示す。図の中で,クラスC1からクラス
C2が矢印で直接結ばれている場合,C1はC2の直接の上位クラスとし,C2はC1の直接の下位クラスとする。
これ以外の関係が追加されてもよいが,次の制約に従うこととする。
a) <standard-generic-function>が<standard-object>の下位クラスであるかどうかは,処理系定義とする。
b) 上の<standard-generic-function>に関する制約及び図1で規定することを除いては,この規格で定義され
るクラス間には,上位下位の関係は存在しない。しかし,処理系が定める追加のクラスと,この規格
で定義するクラスとの間には,処理系が定める上位下位の関係が存在してよい。
c) <null>のクラス優先度リストには,<null>,<symbol>,<list>及び<object>が,この順序で現れる。
d) 利用者は,defclassを用いて,追加のクラスを定義できる。
組込みクラス (built-in class) とは,そのインスタンスの機能が制限されているか又は特別な表現をもつ
クラスとする。defclass定義形式を,組込みクラスの下位クラスを定義するために使用してはならない。包
括関数createが組込みクラスのインスタンスを生成するために使われた場合は,エラーが発生する。
標準クラス (standard class) は,<standard-class>のインスタンスとする。組込みクラスは,<built-in-class>
のインスタンスとする。
直接の上位クラスを指定しないで定義した標準クラスは,<standard-object>及び<object>という名前のク
ラスを除けば,図1に現れるどのクラスとも重複しないことが保証される。
<function>は,すべての関数のクラスとする。<standard-generic-function>は,クラス指定(7.2.1参照)な
しに定義されたすべての包括関数のクラスとする。
11
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
図1 クラス継承
2.3
標準クラス
2.3.1
スロット <standard-class>をメタクラスとするオブジェクトは,0個以上の名前付きスロットをも
つ。オブジェクトのスロットは,そのオブジェクトのクラスによって決定される。各スロットは,その値
として一つのオブジェクトを保持できる。スロットの名前は,識別子とする。
あるスロットが値をもたないとき,そのスロットは未束縛 (unbound) であるという。未束縛のスロット
12
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
の値を取り出そうとした場合は,結果は未定義とする。
スロットの値を格納したり取り出したりすることは,defclass定義形式で定義される包括関数によって行
う。
すべてのスロットは局所的とする。すなわち,複数のインスタンスからアクセスできる共通のスロット
は存在しない。
あるクラスのdefclass定義形式に,ある名前のスロット指定が含まれるとき,そのクラスはその名前の
スロットを定義する (define) という。スロットを定義することは,直ちにスロットを生成することを意味
するのではなく,そのクラスのインスタンスが生成されるごとにスロットが生成されることを意味する。
あるスロットがそのインスタンスの属するクラスによって定義されているか又はそのクラスの上位クラ
スから継承されているとき,そのスロットは,アクセス可能 (accessible) であるという。一つのインスタ
ンスに対しては,ある名前のスロットは,高々一つだけがアクセス可能とする。スロットの継承の詳細は,
7.1.3による。
2.3.2
クラスのインスタンスの生成 包括関数createは,クラスのインスタンスを生成し,それを値とし
て返す。ISLISPは,インスタンスを初期化する方法を指定するために,幾つかの機構を用意している。例
えば,省略時初期値形式を与えることによって,新しく生成されるインスタンスのスロット初期値を指定
することができる。更に,初期化のための包括関数に対してメソッドを追加することによって,柔軟な初
期化が行える。
3. 有効範囲及び存在期間 ISLISPを定める上で,有効範囲及び存在期間の概念は重要となる。前者は構
文の概念とし,後者は意味の概念とする。構文上の構造,特に識別子は,実行時の実体(実行中に生成さ
れるオブジェクト)を参照するために使うが,一つの実体が同時に有効範囲及び存在期間の両方をもつこ
とはできない。有効範囲は,識別子の属性であり,識別子が一意的な意味をもつISLISPテキストの一部分
を指す。存在期間は,あるオブジェクトが存在する期間を指す。
名前空間 (namespace) は,識別子から意味への対応を決定する。ISLISPには,六つの名前空間(変数,
動的変数,関数,クラス,ブロック及びタグ本体のタグ)がある。プログラムの文脈に応じて,一つの識
別子が,最大で六つの意味をもつことができる。例えば,関数適用形式において,演算子位置に識別子が
現れた場合,関数の名前空間がその識別子の意味を決定する。一方,同じ評価形式の引数位置に同じ識別
子が現れた場合,変数の名前空間がその識別子の意味を決定する。
3.1
静的原理 ISLISPは,静的可視性 (lexical visibility) の原理に従って設計されている。この原理は,
ISLISPテキストが,正しく入れ子構造になった静的可視性のブロックから構成されることを意味する。あ
るブロックの中では,そのブロックで定義されたすべての識別子及びそのブロックを包含する外側のブロ
ックで定義されたすべての識別子が可視とする。ある名前空間の識別子は,それを定義する最も内側のブ
ロックによって意味が決まる。
ISLISPは動的束縛 (dynamic binding) の機能も提供する。動的束縛の設定及びアクセスは,専用の機構
(すなわち,defdynamic,dynamic-let及びdynamic)によって行なわれる。動的束縛の値は,時間的に最も
近い時点で実行された活性ブロック (active block) が設定した束縛の値とする。ここで活性ブロックとは,
実行が開始され,その実行がまだ終了していないブロックとする。専用の機構が使われるので,一つの識
別子に,静的な意味及び動的束縛の値の両方が定義されている場所では,それらを同時にアクセスできる。
13
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
3.2
識別子の有効範囲 識別子の有効範囲 (scope) とは,その識別子の意味が定義されているISLISPテ
キストの一部分とする。有効範囲は,定義位置から始まる。定義位置は,識別子の束縛を設定する評価形
式ごとに定める。識別子だけが有効範囲をもつことができる。
ある名前空間において,ある識別子がsaという有効範囲をもち,同じ名前空間における同じ識別子がsa
の内側に有効範囲sbをもつ場合,sbはsaの一部ではない。このとき,内側の有効範囲は,外側の有効範囲
を遮へいする (shadow) という。
参考 個々の評価形式の記述の中で有効範囲を規定する場合,遮へいされる部分も含んだ範囲を記す
ことにする。
ISLISPテキスト全体は,最上位有効範囲 (toplevel scope) と呼ばれる有効範囲で処理される。
(let ((a1 f-a1)
…
(x f-x)
…
(z1 f-z1))
;ここで,a1,…,x,…,z1が使用でき,それらの有効範囲はここから始まる。
(let((a2 f-a2) ;a1,…,x,…,z1は,新しく定義されるかもしれない。しかし,
…
;依然,外側のa1,…,x,….,z1は使用でき,
(x f-x2) ;内側のa2,…,x,…,z2はまだ使用できない。
…
(z2 f-z2));外側のxの有効範囲が,遮へいされる。
;内側のa2,…,x,…,z2の有効範囲が始まる。
…
;ここで,外側のa1,z1及び内側のa2,…,x,…,z2が使用できる。
)
;ここで,a2,…,x,…,z2の有効範囲が終わる。
…
;外側のxの有効範囲が復活する。
)
;ここで,a1,…,x,…,z1の有効範囲が終わる。
図2 有効範囲の例
3.3
個別の有効範囲規則 組込み関数及び組込み定数に対応する識別子の有効範囲は,最上位有効範囲
とする。予約語(1.6参照)は識別子ではないので,静的原理に従わない。予約語は定義できないし,束縛
もできない。
3.4
存在期間 構文の概念である有効範囲に対して,意味の概念である存在期間 (extent) がある。これ
は,実体が生存する期間を表わす。
オブジェクトは,実行中のある時点で生成される。ほとんどの場合,オブジェクトの存在が終わる時点
は決定できない。オブジェクトの存在期間は,オブジェクトが生成された時点に始まり,それへの参照が
不可能になった時点で終了する。この場合,そのオブジェクトは,無制限の存在期間 (indefinite extent) を
もつという。
その他に,実行準備されたテキストに付随する実体を,処理系が生成する場合がある。そのようなオブ
ジェクトの存在期間は,それを定義する構文の起動時点に始まり,活動が終了した時点で終了する。この
とき,そのオブジェクトは,動的存在期間 (dynamic extent) をもつという。
14
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
プログラムの実行中に,定義形式及び次の束縛形式は,起動された時点に束縛を行う。
block
let
with-open-io-file
dynamic-let
let*
with-open-output-file
flet
tagbody
with-standard-input
for
with-error-output
with-standard-output
labels
with-open-input-file
定義形式が設定する束縛は,無制限の存在期間をもつ。局所的な束縛を設定する特殊形式においても,
実行終了時点で束縛が消滅するとは限らない。そのブロックの実行中にそれらの束縛をアクセスする関数
オブジェクトが生成された場合,束縛は,それらの関数オブジェクトのうち,存在期間が最大のものと同
じ存在期間をもつ。
例 (defun copy-cell (x) (cons (car x) (cdr x)))
識別子xの有効範囲は,本体,すなわち, (cons (car x) (cdr x)) となる。xの意味は,本体の全
体で定義される。識別子としてのxは,存在期間をもたない。このdefun形式が実行準備され,
copy-cellが実行準備された関数となる。プログラム実行中,実行準備された関数copy-cellが起動
されるかもしれない。この起動によって,xという名前の変数と,引数として使われるオブジェ
クトとの間に,束縛が生成される。Xの束縛の存在期間は,関数の起動時点に始まり,関数の終
了時点に終わる(一般には,束縛は関数の活動終了後も存在し続ける可能性があるが,この単純
な例では,そのようなことは起こらない。)。xの束縛は関数起動時点に設定 (establish) されると
いい,活動終了時点に解除 (disestablish) されるという。
4. 評価形式及び評価
4.1
評価形式 ISLISPテキストの実行準備が成功していることを前提として,実行が行われる。実行と
は,実行準備された評価形式の活動であり,その結果,値を生成し,副作用を生じることもある。
ISLISPテキストとは,評価形式の並びとする。
この規格では,評価形式が返す値を定めているが,評価形式の部分形式が非局所的脱出(6.7.1参照)を
実行する場合には,戻らないこともある。それゆえ,すべての値の記述は,戻るという条件が存在するこ
とを暗黙の前提とする。
次のものを,ISLISPの正しい評価形式とする。
・ 複合形式 (compound form)
− 特殊形式 (special form)
− 定義形式 (defining form)
− 関数適用形式 (function application form)
− マクロ形式 (macro form)
・ 識別子 (identifier)
・ リテラル (literal)
評価形式は,評価されると,一つのオブジェクトをその値として返す。ただし,戻らない評価形式(例
えば,return-from)もある。
複合形式は, (operator argument*) と記述される。operatorは,特殊演算子,定義演算子,識別子又はラ
ムダ式でなければならない。識別子は,関数(包括関数を含む。)又はマクロの名前でなければならない。
15
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
operatorがリテラルの場合は,違反とする。
最上位形式 (toplevel form) とは,他の評価形式に構文上含まれることがないか,又は一つ以上のprogn
形式の中にだけ入れ子になった評価形式とする。最上位に現れる特殊形式及び関数適用形式を,初期設定
形式 (set-up form) と呼ぶ。定義形式が最上位形式でない場合は,違反とする。
4.2
関数適用形式 関数適用形式 (function application form) は,演算子が関数の名前を与える識別子で
あるか又は演算子がラムダ式である複合形式とする。すべての引数は左から右に順に評価され,その後に
それらの引数で関数が呼び出される。これを適用する (apply) という。関数の適用において,引数は,評
価の結果であるオブジェクトが評価と同じ順序で使われる。
この規格では,関数適用形式を次の記法を使って記述する。
(function-name argument*) →結果のクラス
関数
これは,通常の関数(包括関数以外の関数)を記述する。
(generic-function-name argument*) →結果のクラス
包括関数
これは,包括関数を記述する。
(local-function-name argument*) →結果のクラス
局所関数
これは,指定された静的有効範囲だけで利用できる通常の関数を記述する。
4.3
特殊形式 特殊形式 (special form) とは,その引数が特別な方法で扱われる評価形式とする。例えば,
引数が評価されなかったり,特殊な順序で評価されたりする。ある特殊形式がマクロ(4.5及び8.参照)で
記述されるかどうかは,処理系定義とする。特殊形式は,その演算子位置に特殊演算子 (special operator) が
あることで判別できる。次のものを,特殊演算子とする。
and
dynamic-let
let*
unwind-protect
assure
flet
or
while
block
for
progn
with-error-output
case
function
quote
with-handler
case-using go
return-from with-open-input-file
catch
if
setf
with-open-io-file
class
ignore-errors setq
with-open-output-file
cond
labels
tagbody
with-standard-input
convert
lambda
the
with-standard-output
dynamic
let
throw
これ以外にも,処理系定義の特殊演算子がある場合もある。
この規格では,次の表記で特殊形式を記述する。
(special-operator argument*) →結果のクラス
特殊演算子
4.4
定義形式 定義形式 (defining form) は,名前nameとオブジェクトとの束縛を設定する最上位形式
(4.1参照)とする。この束縛は,定義形式の名前defining-form-nameごとに定められた意味に基づいて,
argumentを操作した結果として設定される。定義形式が最上位形式でない場合は,違反とする。それぞれ
の名前空間において,定義形式は同じ名前に対して2回以上現れてはならない。ただし,メソッド定義の
場合は,名前だけでなくパラメタ記述についても同じものが,2回以上現れてはならない。定義形式は,
その演算子が定義演算子 (defining operator) である複合形式とする。次のものを,定義演算子とする。
defclass
defdynamic
defglobal
defmethod
16
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
defconstantt defgeneric
defmacro
defun
この規格では,次の表記で定義形式を記述する。
(defining-form-name name argument*) →<symbol>
定義演算子
4.5
マクロ形式 マクロ形式は,実行準備の間に展開される。マクロが展開される方法は,8.による。
4.6
評価モデル ここでは,評価についての操作的モデルを規定する。
評価には,二つの段階がある。正しいISLISPテキストは,まず実行準備され,次にその準備されたテキ
ストが実行される。実行準備のための処理は処理系依存とし,準備が完了したテキストの性質も処理系依
存とする。ただし,マクロは実行準備が完了した時点で,展開が完了しているとする(8.参照)。ここでは,
実行については,マクロがすべて展開された評価形式に対して規定する。
実行準備された評価形式は,次のとおり実行される。
a) 評価形式がリテラルの場合,評価形式そのものを結果とする。
b) 評価形式が識別子の場合,現在の静的環境での変数名前空間でその識別子が指定するオブジェクトを
結果とする。現在の静的環境の変数名前空間で,その識別子が束縛されていない場合は,エラーが発
生する(エラー名unbound-variable)(1.8.2参照)。
c) 評価形式が複合形式の場合,次のいずれか一つの場合が,必ず適用される。
1) 演算子が特殊演算子の場合,その評価形式は特殊形式であり,その引数は特殊演算子の定義に従っ
て評価される。例えば,if形式 (if test-form then-form else-form) は,まずtest-formを評価し,次に,
その評価結果に依存してthen-form又はelse-formを評価する。
2) 演算子が定義演算子の場合,第1引数は,識別子とする。残りの引数は,定義形式の仕様に従って
扱われ,その結果のオブジェクトが,適切な名前空間において,識別子に束縛される。
3) 演算子がラムダ式の場合,まず引数が評価される。引数の評価は,左から右へ順に行われる。その
後,引数を評価した結果を実引数 (actual argument) として,ラムダ式で指定された関数を呼び出す。
関数が戻るならば,評価形式の結果は,関数が返す値とする。
例 ((lambda (x) (+ x x)) 4)
⇒ 8
4) 上のいずれでもない場合,複合形式は,関数適用形式とする。評価形式の演算子位置には,識別子
があるものとする。この識別子を現在の静的環境の関数名前空間で評価し,呼び出すべき関数を生
成する。関数名前空間で,その識別子が束縛されていない場合は,エラーが発生する(エラー名
undefined-function)。引数は,左から右へ順に評価される。その後,引数を評価した結果を実引数と
して,関数を呼び出す。関数が戻るならば,評価形式の結果は,関数が返す値とする。
d) 上のいずれでもなければ,エラーが発生する(エラー名undefined-function)。
上のそれぞれの場合に起こり得るエラーについては,1.8.2による。
4.7
関数 関数は,呼び出されるときに,幾つかのオブジェクトを実引数として受け取る (receive) こと
ができる。関数が戻るときには,オブジェクトを値 (value) として返す (return)。関数の束縛は,次のいず
れかで設定することができる。
・ 関数定義形式を使う方法。すなわち,defun,defgeneric又はdefclassの定義形式を使う方法。
・ labels又はfletの特殊形式を使う方法。
(functionp obj) →真偽値
関数
関数functionpは,objが通常の関数又は包括関数である場合はtを返し,それ以外の場合はnilを返す。
objは,いかなるISLISPオブジェクトでもよい。
17
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
例 (functionp (function car)) ⇒t
関数束縛は,labels形式又はflet形式の実行の間に設定されるか,又は関数定義形式で設定される。関数
束縛は,関数名と関数オブジェクトとの対応関係とする。その関数オブジェクトは,関数名が演算子位置
にあるときは名前によって,そうでないときは (function function-name) の評価形式によって指定する。
(function function-name) →<function>
特殊演算子
#ʼfunction-name→<function>
構文
特殊形式のfunctionは,function-nameという名前の関数への参照を表す。この特殊形式は,関数定義形
式,labels形式又はflet形式で定義された識別子を,演算子位置以外の場所で参照するために使用する。
(function function-name) は,#ʼfunction-nameと記述してもよい。
この評価形式は,function-nameという名前の関数オブジェクトを,値として返す。
現在の静的環境の関数名前空間において,識別子function-nameに対する束縛がない場合は,エラーが発
生する(エラー名undefined-function)(1.8.2参照)。function-nameがマクロ,特殊形式又は定義形式の名前
である場合は,結果は未定義とする。
例 (funcall (function -) 3)
⇒ -3
(apply #ʼ-ʼ(4 3))
⇒ 1
(lambda lambda-list form*) →<function>
特殊演算子
ここで,
lambda-list
::=
(identifier* [&rest identifier]) |
(identifier* [:rest identifier])
また,同じ識別子が,一つのlambda-listに2回以上現れてはならない。
lambda形式を実行すると,関数オブジェクトが生成される。
lambda-listは,ラムダリスト (lambda list) と呼ばれ,関数のパラメタを記述する。lambda-listに指定さ
れた識別子の有効範囲は,form*で指定された評価形式の並びとする。この並びの全体を本体と呼ぶ。また,
ラムダリストに&rest又は:restがある場合は,その左側にある各identifierが表すパラメタを必す(須)パ
ラメタ (required parameter) と呼び,右側にあるidentifierの表すパラメタを残余パラメタ (rest parameter)
と呼ぶ。ラムダリストに&restも:restもない場合は,すべてのidentifierの表すパラメタを必すパラメタと
呼ぶ。
関数が引数とともに後で呼び出されたとき(オブジェクトとして別の位置に渡されていても),その関数
の本体は,あたかも,lambda形式があったテキスト位置にあるかのように評価される。ただし,必すパラ
メタが,対応する引数の値に変数名前空間で束縛された状態で評価される。残余パラメタがあるならば,
それは,残りの引数の値のリストに束縛される。関数が受け取った引数の個数が,指定されたlambda-list
と一致しない場合は,エラーが発生する(エラー名arity-error)。
必すパラメタ(及び残余パラメタ)を束縛した後に,本体を実行する。本体が空のときは,nilが値とし
て返る。本体が空でなく,かつ非局所的脱出(6.7参照)で本体から抜け出ない場合には,本体の最後の評
価形式の評価結果が値として返る。
関数が残余パラメタをもつ場合,残余パラメタに束縛されるリストであるL1は,無制限の存在期間をも
つ。L1は,新しく生成されるリストとする。ただし,関数がapplyで呼び出され,残余パラメタがその最
後の引数L2又はL2の後ろの一部分に束縛される場合,L1とL2とがリストを共有するかどうかは,処理系
18
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
定義とする。
例 ((lambda (x y) (+ (* x x) (* y y))) 3 4)
⇒ 25
((lambda (x y &rest z) z) 3 4 5 6)
⇒ (5 6)
((lambda (x y :rest z) z) 3 4 5 6)
⇒ (5 6)
(funcall (lambda (x y) (- y (* x y))) 7 3)
⇒ -18
(labels ((function-name lambda-list form*) *)body-form*) →<object>
特殊演算子
(flet ((function-name lambda-list form*) *)body-form*) →<object>
特殊演算子
labels形式及びflet形式は,関数名前空間において,関数オブジェクトに対する新しい識別子を定義する。
labels形式において,function-nameの有効範囲は,そのlabels形式全体とする。一方,flet形式において
は,識別子の有効範囲はbody-form*だけとする。これらの有効範囲内では,function-nameは, (lambda
lambda-list form*) と同じ振る舞いをする関数オブジェクトに束縛される。ただし,form*内の自由な識別子
は次のとおり処理される。
・ labels形式に対しては,labelsのすぐ外側の静的環境に,与えられた関数のための束縛が追加される。
その環境を用いて,自由識別子の意味を決定する。すなわち,function-nameという関数名は,labels
形式が設定する束縛を参照する。
・ flet形式に対しては,自由識別子の参照は,flet形式のすぐ外側の静的環境で処理される。すなわち,
flet形式が定義するfunction-nameという名前の関数は参照できない。
labels形式又はflet形式を実行すると,関数束縛が設定され,その後,body-form*で指定された本体の評
価形式を左から右に順に実行する。最後の評価形式の値(評価形式がない場合はnil)を,これらの特殊形
式の値とする。
同じfunction-nameが,関数束縛の指定に2回以上現れてはならない。
例 (labels ((evenp (n)
(if(= n 0)
t
(oddp (- n 1))))
(oddp (n)
(if (= n 0)
nil
(evenp (- n 1)))))
(evenp 88))
⇒ t
(flet ((f (x) (+ x 3)))
(flet ((f (x) (+ x (f x))))
(f 7)))
⇒ 17
(apply function-obj* list) →<object>
関数
関数applyは,functionで指定された関数を呼び出す。その引数は,listで指定されたリストの要素をobj*
の後に追加したものとする。functionで指定された関数の返り値が,全体の値となる。
functionが関数でない場合は,エラーが発生する(エラー名domain-error)。各objは,いかなるISLISP
19
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
オブジェクトでもよい。listがnilで終わるリストでない場合は,エラーが発生する(エラー名
improper-argument-list)。
例 (apply (if (< 1 2) (function max) (function min))
1 2 (list 3 4))
⇒ 4
(defun compose (f g)
(lambda (:rest args)
(funcall f (apply g args)))))
⇒ compose
(funcall (compose (function sqrt) (function*)) 12 75)
⇒ 30
(funcall function obj*) →<object>
関数
関数funcallは,functionで指定された関数を呼び出し,その関数の返り値をfuncall自身の値として返す。
funcallのi番目の引数 (i≥2) は,その関数の (i−1) 番目の引数になる。funcallは,applyを使用して,次
のとおり定義できる。
(defun funcall (function :rest arguments)
(apply function arguments))
functionが関数でない場合は,エラーが発生する(エラー名domain-error)。各objは,いかなるISLISP
オブジェクトでもよい。
例 (let ((x ʼ(1 2 3)))
(funcall (cond ((listp x) (function car))
(t (lambda (x) (cons x 1))))
x))
⇒ 1
4.8
定義演算子 定義形式によって定義される名前は,最上位有効範囲全体で使うことができるが,
ISLISPテキスト単位における実行準備された最上位形式は,左から右に順に実行される。
一つの名前空間で同じ名前をもつ二つの定義形式は,同じ最上位有効範囲で使ってはならない。
(defconstant name form) →<symbol>
定義演算子
defconstant形式は,名前付き定数を最上位有効範囲の変数名前空間に定義する。nameの有効範囲は,form
の部分を除いた最上位有効範囲全体とする。
nameは,大域的な定数とするが,束縛形式を用いて局所的にnameという名前の変数を束縛してもよい。
formで指定された評価形式の評価の結果が,nameという名前の変数に束縛される。この束縛及びform
を評価した結果生成されたオブジェクトは,変更不可能とする。nameという名前の記号を,この定義形式
の値とする。
例 (defconstant e 2.7182818284590451) ⇒ e
e
⇒ 2.7182818284590451
(defun f () e)
⇒ f
(f)
⇒ 2.7182818284590451
(defglobal name form) →<symbol>
定義演算子
defglobal形式は,最上位有効範囲の変数名前空間に識別子を定義する。nameの有効範囲は,formの部
20
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
分を除いた最上位有効範囲全体とする。
formは,nameという名前の変数の初期値を計算するために評価される。したがって,defglobalは変数
を定義するためだけに使用し,変数を変更するためには使用できない。nameという名前の記号を,この定
義形式の値とする。
nameに対して,束縛形式を用いて静的な変数束縛を局所的に設定してもよい。この場合,局所的な束縛
は,defglobalが定義したnameの束縛を遮へいする。
例 (defglobal today ʼwednesday)
⇒ today
today
⇒ wednesday
(defun what-is-today () today)
⇒ what-is-today
(what-is-today)
⇒ wednesday
(let ((what-is-today ʼthursday)) (what-is-today))
⇒ wednesday
(let ((today ʼthursday)) (what-is-today))
⇒ wednesday
(defdynamic name form) →<symbol>
定義演算子
defdynamic形式は,動的変数の名前空間に,動的変数を定義するために使用する。nameの有効範囲は,
formの部分を除いた最上位有効範囲全体とする。
nameという名前の記号を,この定義形式の値とする。
例 (defdynamic *color* ʼred)
⇒ red
(dynamic *color*)
⇒ red
(defun what-color () (dynamic *color*))
⇒ what-color
(what-color)
⇒ red
(dynamic-let ((*color* ʼgreen)) (what-color))
⇒ green
(defun function-name lambda form*) →<symbol>
定義演算子
defun形式は,function-nameを,関数名前空間の識別子として定義する。function-nameは, (lambda
lambda-list form*) と等価な関数オブジェクトに束縛される。
function-nameの有効範囲は,最上位有効範囲全体とする。したがって,defunによる関数定義では,再
帰が許される。すなわち,form*の中で,定義しようとしている関数をfunction nameという名前で用いる
ことができる。function-nameとそれに対応する関数オブジェクトとの束縛は,変更不可能とする。
defunはfunction-nameという名前の記号を返す。関数本体form*に現れる自由識別子(すなわち,ラムダ
リストに含まれない識別子)は,静的有効範囲規則に従うものとする。
例 (defun caar (x) (car (car x))) ⇒ caar
5. 述語
5.1
真偽値 値t及び値nilは,真偽値 (boolean) と呼ばれる。tは真を表し,nilは偽を表す唯一の値と
する。述語 (predicate) は,真偽値関数 (boolean function) とも呼ばれ,その引数が条件を満たす場合はt
を返し,そうでなければnilを返す。
(tに限らず)nil以外のすべてのオブジェクトは,真として扱う。オブジェクトは,このように真又は
nilとして扱われる場合,準真偽値 (quasi-boolean) と呼ぶ。
21
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
tは記号tを表す識別子であり,nilは記号nilを表す識別子とする(記号nilは,空リストでもある。)。
nilは,クラス<null>の唯一のインスタンスとする。
真偽値関数と同様に,and形式及びor形式は,真又は偽を返す。しかし,返される値は,条件が満たさ
れない場合はnilであり,そうでなければnil以外の値とする。つまり,and及びorは,準真偽値を値とす
る。
t→<symbol>
名前付き定数
nil→<null>
名前付き定数
tは,記号tを値とする名前付き定数とする。nilは,記号nilを値とする名前付き定数とする。
5.2
クラス述語 次の関数は,1引数のクラス述語とする。
basic-array*-p floatp
integerp
stringp
basic-array-p
functionp
listp
symbolp
basic-vector-p general-array*-p
null
characterp
general-vector-p
numberp
consp
generic-function-p streamp
なお,関数instancepは,クラスのインスタンスか否かを判定する,2引数の述語とする。
5.3
等価性
(eq obj1 obj2) →真偽値
関数
(eql obj1 obj2) →真偽値
関数
関数eq及び関数eqlは,引数obj1と引数obj2とが,同一のオブジェクトであるか否かを判定する。これ
らの関数は,二つの引数が同一のオブジェクトであればtを返し,そうでなければnilを返す。二つのオブ
ジェクトは,それらを(オブジェクトの変更なしに)区別する操作がなく,かつ,一つのオブジェクトの
変更がもう一つのオブジェクトを同じように変更する場合に同一とする。
関数eqでは,引数がいずれも数値であるか,又はいずれも文字である場合は,結果は未定義とする。関
数eqlでは,数値及び文字に対する意味は次のとおり定義する。
・ 引数obj1及び引数obj2が数値であれば,eqlは,二つの引数が同じクラスの直接インスタンスであり,
かつ,同じ値をもつか否かを判定する。
処理系が,正のゼロ及び負のゼロを異なる値として実装していれば, (eql 0.0 -0.0) はnilを返す。
-0.0が読み込まれた場合に,値0.0と解釈されるならば, (eql 0.0 -0.0) はtを返す。
・ 引数obj1及び引数obj2が文字ならば,eqlは,それらが同じ文字か否か(char=参照)を判定する。
例 (eql () ())
⇒ t
(eq () ())
⇒ t
(eql ʼ() ʼ())
⇒ t
(eq ʼ() ʼ())
⇒ t
(eql ʼa ʼa)
⇒ t
(eq ʼa ʼa)
⇒ t
(eql ʼa ʼA)
⇒ t
(eq ʼa ʼA)
⇒ t
(eql ʼa ʼb)
⇒ nil
(eq ʼa ʼb)
⇒ nil
22
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(eql ʼf ʼnil)
⇒ nil
(eq ʼf ʼml)
⇒ nil
(eql 2 2)
⇒ t
(eq 2 2)
⇒ nil又はt (処理系定義)
(eql 2 2.0)
⇒ nil
(eq 2 2.0)
⇒ nil
(eql 100000000 100000000)
⇒ t
(eq 100000000 100000000)
⇒ nil又はt(処理系定義)
(eql 10.00000 10.0)
⇒ t
(eq 10.00000 10.0)
⇒ nil又はt(処理系定義)
(eql (cons 1 2) (cons 1 2))
⇒ nil
(eq (cons 1 2) (cons 1 2))
⇒ nil
(let ((x ʼ(a))) (eql x x))
⇒ t
(let ((x ʼ(a))) (eq x x))
⇒ t
(eql ʼ(a) ʼ(a))
⇒ nil又はt(処理系定義)
(eq ʼ(a) ʼ(a))
⇒ nil又はt(処理系定義)
(let ((x ʼ(b))
(y ʼ(a b)))
(eql x (cdr y)))
⇒ nil又はt(処理系定義)
(let ((x ʼ(b))
(y ʼ(a b)))
(eq x (cdr y)))
⇒ nil又はt(処理系定義)
(eql ʼ(b) (cdr ʼ(a b)))
⇒ nil又はt(処理系定義)
(eq ʼ(b) (cdr ʼ(a b)))
⇒ nil又はt(処理系定義)
(let ((p (lambda (x) x)))
(eql p p))
⇒ t
(let ((p (lambda (x) x)))
(eq p p))
⇒ t
(let ((x "a")) (eql x x))
⇒ t
(let ((x "a")) (eq x x))
⇒ t
(eql "a" "a")
⇒ nil又はt(処理系定義)
(eq "a" "a")
⇒ nil又はt(処理系定義)
(let ((x ""))(eql x x))
⇒ t
(let ((x ""))(eq x x))
⇒ t
(eql "" "")
⇒ nil又はt(処理系定義)
(eq "" "")
⇒ nil又はt(処理系定義)
(eql #\a #\A)
⇒ nil
(eq #\a #\A)
⇒ nil
(eql #\a #\a)
⇒ t
(eq #\a #\a)
⇒ nil又はt(処理系定義)
23
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(eql #\space #\Space)
⇒ t
(eq #\space #\Space)
⇒ nil又はt(処理系定義)
(eql #\space #\space)
⇒ t
(eq #\space #\space)
⇒ nil又はt(処理系定義)
(equal obj1 obj2) →真偽値
関数
関数equalは,引数obj1及び引数obj2が同形 (isomorphic),すなわち,引数obj1及び引数obj2が等価な値
をもつ同じ構造を表すか否かを判定する。equalは,同形の場合はtを返し,そうでなければnilを返す。
正確には,次のとおり判定する。
引数obj1と引数obj2とが同じクラスの直接インスタンスである場合,その二つがeqlであるか又は次の
いずれかが成り立つときにequalはtを返す。これ以外の場合は,nilを返す。
a) リスト
(and (equal (car obj1) (car obj2))
(equal (cdr obj1) (cdr obj2)))
b) 配列
(equal (array-dimensions obj1)
(array-dimensions obj2))
が成り立ち,かつ,すべての正しい参照 (aref obj1 ind1 ... indn) に対して,次の条件が成り立つ。
(equal (aref obj1 ind1 ...indn)
(aref obj2 ind1 ...indn))
obj1及びobj2は,いかなるISLISPオブジェクトでもよい。
例 (equal ʼa ʼa)
⇒ t
(equal 2 2)
⇒ t
(equal 2 2.0)
⇒ nil
(equal ʼ(a) ʼ(a))
⇒ t
(equal ʼ(a (b) c) ʼ(a (b) c))
⇒ t
(equal (cons 1 2) (cons 1 2))
⇒ t
(equal ʼ(a) (list ʼa))
⇒ t
(equal "abc" "abc")
⇒ t
(equal (vector ʼa) (vector ʼa))
⇒ t
(equal #(a b) #(a b))
⇒ t
(equal #(a b) #(a c))
⇒ nil
(equal "a" "A" )
⇒ nil
5.4
論理演算
(not obj) →真偽値
関数
関数notは,論理否定であり,引数objがnilであればtを返し,そうでなければnilを返す。objは,い
かなるISLISPオブジェクトでもよい。
例 (not t)
⇒ nil
(not ʼ())
⇒ t
24
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(not ʼnil)
⇒ t
(not nil)
⇒ t
(not 3)
⇒ nil
(not (list))
⇒ t
(not (list 3))
⇒ nil
(and form*) →<object>
特殊演算子
andは,逐次的な論理積とする。引数form*は,そのいずれかのformの評価結果がnilであるか,又は引
数がなくなるまで,左から右に順に評価される。引数のいずれかの評価結果がnilであれば,andはnilを
返し,そうでなければ最後に評価した引数formの値を返す。and形式は,次の式と同値とする。
(and)
≡ ʼt
(and form)
≡ form
(and form1 form2 ... formn)
≡ (if form1 (and form2...formn) ʼnil) (2)
注(2) ifの定義については,6.4参照。
例 (and (= 2 2) (> 2 1))
⇒ t
(and (= 2 2) (< 2 1))
⇒ nil
(and (eql ʼa ʼa) (not (> 1 2)))
⇒ t
(let ((x ʼa)) (and x (setq x ʼb)))
⇒ b
(let ((x nil)) (and x (setq x ʼb)))
⇒ nil
(let ((time 10))
(if (and (< time 24) (> time 12))
(- time 12) time))
⇒ 10
(let ((time 18))
(if (and (< time 24) (> time 12))
(- time 12) time))
⇒ 6
(or form*) →<object>
特殊演算子
orは,逐次的な論理和とする。引数form*は,そのいずれかのformの評価結果がnil以外の値であるか,
又は引数がなくなるまで,左から右に順に評価される。orは,引数のいずれかの評価結果がnil以外の値
であれば,そのnil以外の値を返し,そうでなければnilを返す。or形式は,次の式と同値とする。
(or)
≡ ʼnil
(or form)
≡ form
(or form1 form2 ... formn) ≡ ((lambda (var) (if var var (or form2...formn))) form1)
ここで,varは,form2...formnに現れないものとする。
例 (or (= 2 2) (> 2 1))
⇒ t
(or (= 2 2) (< 2 1))
⇒ t
(let ((x ʼa)) (or x (setq x ʼb)))
⇒ a
(let ((x nil)) (or x (setq x ʼb)))
⇒ b
25
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
6. 制御構造
6.1
定数 定数には,リテラル,引用形式及び名前付き定数の3種類がある。引用形式については,quote
参照。名前付き定数については,defconstant参照。
定数の値を変更しようとした場合は,結果は未定義とする。
constant →<object>
構文
クラス<basic-array>,<character>及び<number>のインスタンスは,リテラル定数とする。リテラル定数
constantを評価した結果は,そのconstant自身とする。
例 #2A((a b c) (d e f))
⇒ #2A((a b c) (d e f))
#\a
⇒ #\a
145932
⇒ 145932
"abc"
⇒ "abc"
#(abc)
⇒ #(abc)
(quote obj) →<object>
特殊演算子
ʼobj →<object>
構文
quote形式は,引用形式 (quoted expression) と呼ばれ,ISLISPテキストにオブジェクトobjを埋め込むた
めに使用する。quote形式の評価結果は,objとする。
(quote obj)は,ʼobjと記述してもよい。
例 (quote a)
⇒ a
(quote #(a b c))
⇒ #(a b c)
(quote (+ 1 2))
⇒ (+ 1 2)
ʼ()
⇒ nil
ʼa
⇒ a
ʼ#(a b c)
⇒ #(a b c)
ʼ(car 1)
⇒ (car 1)
ʼ(+ 1 2)
⇒ (+ 1 2)
ʼ(quote a)
⇒ (quote a)
ʼʼa
⇒ (quote a)
(car ʼʼa)
⇒ quote
引用形式の値を変更しようとした場合は,結果は未定義とする。
6.2
変数 変数束縛 (variable binding) は,変数束縛形式の実行又は関数の起動によって設定される。
変数 (variable) は,識別子で表され,その識別子とISLISPオブジェクトとの間の結合を設定する。この結
合は,setf形式又はsetq形式を使って(代入によって),変更できる。
変数束縛形式には次のものがある。
defglobal let let* for
var →<object>
構文
変数varの値は,その変数の束縛によって,varと結合されているオブジェクトとする。
例 (defglobal x 0)
⇒ x
26
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
x
⇒ 0
(let ((x 1)) x)
⇒ 1
x
⇒ 0
(setq var form) →<object>
特殊演算子
setq形式は,識別子varで表される変数への代入を表す。この結果として,formの値が識別子varの値
となる。
setq形式は,引数formを評価した結果を返す。この結果は,識別子varで表される変数束縛を(もし変
更可能ならば)変更するために用いられる。setq形式は,束縛の変更だけに用い,変数束縛の設定に用い
るものではない。setq形式は,defglobal,let,let*,for又はラムダ式で設定される変数varの有効範囲の中
に含まれていなければならない。
例 (defglobal x 2)
⇒ x
(+ x 1)
⇒ 3
(setq x 4)
⇒ 4
(+ x 1)
⇒ 5
(let ((x 1)) (setq x 2) x)
⇒ 2
(+ x 1)
⇒ 5
(setf place form) →<object>
特殊演算子
setf形式は,一般化された代入に使う。
setf形式は,場所を指定するplaceを受け取り,評価形式formの評価結果をその場所に格納する。評価
形式placeは,全体が評価されるのではなく,結果を格納する場所を決定するために,placeの部分形式が
左から右に順に評価される。placeが識別子で表される場合には,setfはsetqと全く同じ動作をする。setf
形式は,formの評価結果を返す。setf形式の正しい場所指定は,次のとおりとする。
変数
var
動的束縛
(dynamic var)
配列の要素
(aref basic-array z1...zn)
一般配列の要素
(garef general-array z1...zn)
リストの要素
(elt list z)
ベクタの要素
(elt basic-vector z)
コンスのcar要素
(car cons)
コンスのcdr要素
(cdr cons)
記号の属性
(property symbol property)
クラスのインスタンスのスロット
(reader-function-name instance)
ここで,reader-function-nameは,: accessor任意機能(7.1参照)に指定した識別子とする。
また,場所指定は,(実行準備の段階で)場所指定に展開されるマクロ形式であるか,setfが定義されて
いる演算子の関数適用形式であるか,又は (setf op) という名前の包括関数が定義されている演算子opの
関数適用形式であってよい。後の二つの場合には,その関数は引数として,代入される新しい値と関数適
用形式の引数を評価して得られたオブジェクトとを受け取る。
27
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
例 (setf (car x) 2)
⇒ 2
コンスxにおいて,そのcarは2となる。
(defmacro first (spot)
ʼ(car ,spot))
⇒ first
(setf (first x) 2)
⇒ 2
コンスxにおいて,そのcarは2となる。
(let ((var form) *) body-form*) →<object>
特殊演算子
let形式は,一連の評価形式body-form*(まとめてbodyと呼ぶ。)に対して,識別子の有効範囲を定義す
るために使われる。対のリスト (var form)*は,let変数リストと呼ばれる。識別子varの有効範囲は,body
とする。
let変数リスト中の各formは,左から右に順に評価される。そして識別子varで表される各変数は,対応
する値に初期化される。これらの束縛と,既存の束縛とを使って,body-form*が順に評価される。letの返
り値は,本体の最後のbody-formを評価した結果(body-formがない場合は,nil)とする。
同じvarが,let変数リストに2回以上現れてはならない。
備考 この形式は特殊形式であるが,書換え規則が次のように定義されたマクロと考えてもよい。
(let ( ) body-form*)
≡ (progn body-form*)
(3)
(let ((var1 form1)
≡ ((lambda (var1 var2 ... varn) body-form*)
(var2 form2)
form1 form2 ... formn)
(4)
...
(varn formn))
body-form*)
注(3) prognの定義については,6.5参照。
(4) lambdaの定義については,4.7参照。
例 (let ((x 2) (y 3))
(* x y))
⇒ 6
(let ((x 2) (y 3))
(let ((x 7)
(z (+ x y)))
(* z x)))
⇒ 35
(let ((x 1) (y 2))
(let ((x y) (y x))
(list x y)))
⇒ (2 1)
(let* ((var form) *) body-form*) →<object>
特殊演算子
let*形式は,一連の評価形式body-form*(まとめてbodyと呼ぶ)に対して,識別子の有効範囲を定義す
28
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
るために使われる。最初の部分形式(let*変数リスト)は,対 (var form) のリストとする。識別子varの有
効範囲は,本体body及びlet*変数リスト中の対 (var form) の後のすべてのformとする。
各対 (var form) に対して次が実行される。その時点で有効な束縛の文脈で,formが評価される。評価結
果は,識別子varを名前とする変数に束縛される。これらの変数束縛は,現在有効な識別子の集合を拡大
する。場合によっては(同じ名前の変数が外側で定義されている場合),以前の変数束縛を遮へいする。そ
して,この拡大又は修正された環境で,body-form*が順に評価される。let*の返り値は,本体の最後の
body-formの評価結果(body-formがなければnil)とする。
備考 この形式は特殊形式であるが,書換え規則が次のように定義されたマクロと考えてもよい。
(let* () body-form*)
≡ (progn body-form*)
(let* ((var1 form1)
≡ (let ((var1 form1))
(var2 form2)
(let ((var2 form2))
...
...
(varn formn))
(let ((varn formn))
body-form*)
body-form*)...))
例 (let ((x 2) (y 3))
(let* ((x 7)
(z (+ x y)))
(* z x)))
⇒ 70
(let ((x 1) (y 2))
(let* ((x y) (y x))
(list x y)))
⇒ (2 2)
6.3
動的変数 動的変数は,動的変数の名前空間における識別子varとISLISPオブジェクトとの結合と
する。動的変数は,動的束縛を実装する。
動的変数は,defdynamicによって大域的に定義されるか,又はdynamic-letの実行によって設定される。
defdynamicで定義された動的変数束縛は無限に存在し続ける。これに対して,dynamic-letで設定された
動的変数束縛は,この特殊形式の実行の終了によって消滅する。
動的変数の値は, (dynamic var) によって参照できる。
(dynamic var) →<object>
特殊演算子
この特殊形式は,動的変数の参照を表す。この特殊形式は,defdynamic又はdynamic-letで定義された変
数varの存在期間内だけで使用できる。
活動中,最も近くに設定され,かつ,現在も有効な変数varの動的束縛の値が返される。そのような束
縛が存在しない場合は,エラーが発生する(エラー名unbound-variable)。
(setf (dynamic var) form) →<object>
特殊形式
この特殊形式は,動的変数への代入を表す。この特殊形式は, (dynamic var) が使用できるところなら,
どこででも使うことができる。
formが評価され,その結果が変数varの動的束縛を変更するために使用される。変数varが動的な値を
もたない場合は,エラーが発生する(エラー名unbound-variable)。dynamicに対するsetfは,束縛の変更
29
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
にだけ用いられ,束縛の設定には用いられない。
(dynamic-let ((var form)*)body-form*) →<object>
特殊演算子
dynamic-let形式は,動的変数束縛の設定に使われる。最初の部分式(dynamic-let変数リスト)は,対 (var
form) のリストとする。dynamic-letで定義される識別子varの有効範囲は,最上位有効範囲全体とする。
各varの束縛の存在期間は,dynamic-letの本体の実行中とする。dynamic-let形式は,指定されたすべての
varに対する動的変数束縛を設定する。
varという名前の動的変数への参照は,dynamic形式を使って行わなければならない。
すべての初期化形式は,左から右に順に評価され,値はそれぞれ対応するvarと対応付けられる。これ
らの追加された動的束縛及び既に存在する可視な識別子の束縛を使って,評価形式body-form*が順に評価
される。
dynamic-letの返り値は,本体の最後のbody-formの値(body-formがない場合は,nil)とする。dynamic-let
から制御が離れるときに束縛は解消される。
例 (defun foo (x)
(dynamic-let ((y x))
(bar 1)))
⇒ foo
(defun bar (x)
(+ x (dynamic y)))
⇒ bar
(foo 2)
⇒ 3
6.4
条件式
(if test-form then-form [else-form]) →<object>
特殊演算子
if形式は,まずtest-formを評価する。その結果がnil以外の値であれば,then-formを評価し,その値を
返す。そうでなければ(もしtest-formがnilを返すならば),else-formを評価し,その値を返す。
else-formがない場合は,nilが省略されたものとする。
例 (if (> 3 2) ʼyes ʼno)
⇒ yes
(if (> 2 3) ʼyes ʼno)
⇒ no
(if (> 2 3) ʼyes)
⇒ nil
(if (>3 2) (- 3 2) (+ 3 2))
⇒ 1
(let ((x 7))
(if (< x 0) x (- x)))
⇒ -7
(cond (test form*)*) →<object>
特殊演算子
condの実行では,節 (test form*) を順に走査し,各節のtestを評価する。testがnil以外の値を返せば,
走査を停止し,対応する節のform*が順に評価され,その最後のformの値が返される。どのtestの値も真
でなければ,nilが返される。testが真である節にformが一つもなければ,testの値が返される。
cond形式は,次と同値とする。
(cond)
≡ nil
(cond (test1)
≡ (or test1
(test2 form2*)
(cond (test2 form2*)
...)
...))
30
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(cond (test1 form1+)
≡ (if test1
(test2 form2*)
(progn form1+)
...)
(cond (test2 form2*)
...))
例 (cond ((> 3 2) ʼgreater)
((< 3 2) ʼless))
⇒ greater
(cond ((> 3 3) ʼgreater)
((< 3 3) ʼless))
⇒ nil
(cond ((> 3 3) ʼgreater)
((< 3 3) ʼless)
(t ʼequal))
⇒ equal
(case keyform ((key*) form*)* [(t form*)]) →<object>
特殊演算子
(case-using predform keyform ((key*) form*)* [ (t form*)]) →<object>
特殊演算子
case形式及びcase-using形式は,分類形式 (case form) と呼ばれ,一連の節の中から評価形式keyformの
値に一致する節を実行する機構を提供する。
実行される節は,キーの集合で識別される。キーkeyは,いかなるオブジェクトでもよい。最後の節の
キーリストがtである場合は,いずれのキーもkeyformに一致しないときに,その最後の節が実行される。
keyformは,分類形式の実行開始時に計算される評価形式とする。keyformの評価結果がkeyと一致すれ
ば,対応する節内の評価形式が順に評価され,最後の値が分類形式全体の値として返される。caseは,一
致するかどうかをeqlによって判断する。case-usingは,一致の判断をpredformの評価結果を用いて行う。
predformは,keyformの評価結果とkeyとを引数として受け取る真偽値関数又は準真偽値関数でなければな
らない。一致したkeyにformがなければ,分類形式はnilを返す。keyformの値がすべてのkeyと異なり,
かつ最後の節のキーリストがtであれば,その節の評価形式が順に評価され,最後の評価形式の値が分類
形式の結果となる。keyformの値がすべてのkeyと異なり,かつ最後の節のキーリストがtでなければ,分
類形式はnilを返す。
一つの分類形式では,同じkeyは2回以上現れてはならない。
例 (case (* 2 3)
((2 3 5 7) ʼprime)
((4 6 8 9) ʼcomposite))
⇒ composite
(case (car ʼ(c d))
((a) ʼa)
((b) ʼb))
⇒ nil
(case (car ʼ(cd))
((a i u e o) ʼvowel)
31
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
((y) ʼsemivowel)
(t ʼconsonant))
⇒ consonant
(let ((char #\u))
(case char
( (#\a #\i #\u #\e #\o) ʼvowels)
(t ʼconsonants)))
⇒ vowels
(case-using #ʼ= (+ 1.0 1.0)
((1) ʼone)
((2) ʼtwo)
(t ʼmore))
⇒ two
(case-using #ʼstring= "bar"
(("foo") 1)
(("bar") 2))
⇒ 2
6.5
評価形式の逐次実行
(progn form*) →<object>
特殊演算子
progn形式は,form*を順に評価し,その最後の評価形式の評価結果を返す。すべてのformが,左から右
に順に評価される。最後の評価形式以外のすべてのformの値は,破棄される。したがって,それらの評価
形式は,副作用のためだけに実行される。formをもたないprognは,nilを返す。
例 (defglobal x 0)
⇒ x
(progn
(setq x 5)
(+ x 1))
⇒ 6
(progn
(format (standard-output) "4 plus 1 equals")
(format (standard-output) "~D" (+ 4 1)))
⇒nil
これは,4 plus 1 equals 5を印字する。
6.6
繰返し
(while test-form body-form*) →<null>
特殊演算子
while形式は,test-formが真を返す間,body-form*の実行を繰り返す。詳細を次に示す。
a) test-formを評価する。その値をVtとする。
b) Vtがnilであれば,while形式は直ちにnilを返す。
c) Vtがnil以外の値であれば,一連の評価形式body-form*を左から右に順に評価する。
d) body-form*の評価が正常に終了した場合,while形式は再びa)から実行する。
例 (let ((x ʼ()) (i 5))
32
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(while (> i 0) (setq x (cons i x)) (setq i (- i 1)))
x)
⇒ (1 2 3 4 5)
(for (iteration-spec*) (end-test result*) form*) →<object>
特殊演算子
ここで,
iteration-spec
::=
(var init [step])
for形式は,本体と呼ばれる評価形式の並びform*を繰り返し実行する。for形式には,局所的な変数を表
す識別子の集合,それらの変数の初期化及び繰返しごとの更新を指定する。終了条件が満たされる場合,
繰返しを終了し,指定された値を返す。
各識別子varの有効範囲は,本体,すべてのstep,end-test及びresult*とする。stepは省略でき,その場
合の効果は, (var init) の代わりに (var init var) と書いたものと同じとする。
for形式は,次のとおり実行される。各init形式が,左から右に順に評価される。そして,各値は,対応
する識別子varで表される変数の初期値として使われ,繰返しが開始される。
各繰返しは,end-testの評価で始まる。結果がnilであれば,本体の評価形式が順に評価される。これら
の評価形式の値は,破棄される。次に各step形式が左から右に順に評価され,それらの値が対応する変数
に代入され,次の繰返しが開始される。end-testがnil以外の値を返せば,result*が左から右に順に評価さ
れ,最後の値がfor形式の値として返される。resultが一つもなければ,for形式の値はnilとする。
例 (for ((vec (vector 0 0 0 0 0))
(i 0 (+ i 1)))
((= i 5) vec)
(setf (elt vec i) i))
⇒ #(0 1 2 3 4)
(let ((x ʼ(1 3 5 7 9)))
(for ((x x (cdr x))
(sum 0 (+ sum (car x))))
((null x) sum)))
⇒ 25
6.7
非局所的脱出
6.7.1
非局所的脱出の設定及び起動 ISLISPでは,非局所的脱出を実行する次の三つの方法を定義する。
脱出先の指定
設定する評価形式 起動する評価形式 動作
ブロック名
block
return-from
静的脱出
捕そくタグ
catch
throw
動的脱出
タグ本体のタグ tagbody
go
制御の静的移行
非局所的脱出 (non-local exit) は,それを起動した特殊形式から,脱出先 (destination) と呼ばれるプログ
ラム内のあらかじめ設定された位置へ制御を移行し,場合によってはデータの転送も行う操作とする。
静的脱出 (lexical exit) は,return-from形式から,それを静的にも動的にも含んでいるblock形式への非
局所的脱出であり,block形式がreturn-fromに指定されたオブジェクトを返すようにする。
動的脱出 (dynamic exit) は,throw形式から,それを動的に(しかし必ずしも静的ではなく)含むcatch
形式への非局所的脱出であり,catch形式がthrow形式に指定されたオブジェクトを返すようにする。
制御の静的移行 (lexical transfer of control) は,go形式から,それを静的にも動的にも含んでいるtagbody
33
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
内のタグ付き位置への非局所的脱出とする。
非局所的脱出が起動されると,制御が移行される脱出先よりも後に設定された脱出先は,直ちに無効と
なる。
(block name form*) →<object>
特殊演算子
(return-from name result-form) 制御の移行及びデータの転送
特殊演算子
block形式は,form*を左から右に順に実行する。最後のformが正常に終了した場合,それが返す値がblock
形式の返す値とする。
block形式のnameは評価されない。それは識別子でなければならない。nameの有効範囲は,本体form*
とする。すなわち,いずれかのformにテキスト上で含まれるreturn-from形式だけが,そのブロックを脱
出できる。nameに対する束縛は,動的存在期間をもつ。
return-from形式が実行されると,result-formが評価される。評価が正常に終了すれば,その値は,
return-fromの呼出しを静的に含み,同じnameをもつ最も内側のblock形式の値として返される。
return-from形式は,blockから戻るために使う。return-from形式のnameは評価されず,識別子でなけれ
ばならない。同じnameをもつblockが,return-fromの呼出しを静的に含んでいなければならない。
result-formが生成する値は,対応するblock形式から直ちに返される。return-fromは,戻ることはなく,
また値をもたない。
blockを出た後で,そのblockから脱出しようとする場合は,エラーが発生する(エラー名control-error)。
nameが識別子でない場合は,違反とする。対応する名前をもつブロックが存在しない場合も,違反とす
る。その他のエラーについては,6.7.2参照。
例 (block x
(+ 10 (return-from x 6) 22)) ;;;悪いプログラム書法
⇒ 6
(defun f1 ()
(block b
(let ((f (lambda () (return-from b ʼexit))))
… ; 大規模計算
(f2 f))))
⇒ f1
(defun f2 (g)
… ; 大規模計算
(funcall g))
⇒ f2
(f1)
⇒ exit
(block sum-block
(for ((x ʼ(1 a 2 3) (cdr x))
(sum 0 (+ sum (car x))))
((null x) sum)
(cond ((not (numberp (car x))) (return-from sum-block 0))))))
⇒ 0
34
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(defun bar (x y)
(let ((foo #ʼcar))
(let ((result
(block b1
(setq foo (lambda () (return-from b1 ʼfirst-exit)))
(if x (return-from b1 ʼsecond-exit) ʼthird-exit))))
(if y (funcall foo) nil)
result)))
⇒ bar
(bar t nil)
⇒ second-exit
(bar nil nil)
⇒ third-exit
(bar nil t)
エラーが発生する。
(bar t t)
エラーが発生する。
(catch tag-form form*) →<object>
特殊演算子
(throw tag-form result-form) 制御の移行及びデータの転送
特殊演算子
catch形式及びthrow形式は,構造化された動的な非局所的脱出機能を提供する。catch形式及びthrow形
式は,catchのtag-form及びthrowのtag-formの評価結果が,同一のオブジェクトになる場合,対応すると
呼ばれる。このオブジェクトを捕そくタグ (catch tag) と呼ぶ。捕そくタグは,数値及び文字以外のいかな
るオブジェクトでもよい。捕そくタグの比較は,eqで行う。
catch形式は,まずtag-formを評価して捕そくタグを生成し,次に各formを左から右に順に実行する。
すべてのformの実行が正常に終了した場合,最後のformの返す値が,catch形式の値として返される。
catch形式C0のform*の実行に先立って,捕そくタグT0と実行する評価形式C0との間の対応が動的に設
定され,C0の実行終了時にこの対応は解除される。同じ捕そくタグT0に対して外側の対応があれば,それ
はC0のform*の実行中は遮へいされる。すなわち,T0の最も最近(最も内側)の対応だけが見えるものと
する。
throw形式が実行されると,tag-formを評価して捕そくタグT1を生成し,次にresult-formを評価して結
果R1を生成する。T1と実行中のあるcatch形式C1との間に対応があれば,C1の値としてR1が直ちに返さ
れる。throw形式は,最上位有効範囲全体のどこにあってもよい。すなわち,C1に静的に含まれている必
要はない。
T1に対するcatch形式が存在しない場合は,エラーが発生する(エラー名control-error)。その他のエラ
ーについては,6.7.2参照。
例 (defun foo (x)
(catch ʼblock-sum (bar x)))
⇒ foo
(defun bar (x)
(for ((1 x (cdr 1))
(sum 0 (+ sum (car 1))))
((null 1) sum)
(cond ((not (numberp (car 1))) (throw ʼblock-sum 0)))))
⇒ bar
35
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(foo ʼ(1 2 3 4))
⇒ 10
(foo ʼ(1 2 a 4))
⇒ 0
(tagbody {tagbody-tag | form}*) →<object>
特殊演算子
(go tagbody-tag) 制御の移行
特殊演算子
tagbodyは,各formを左から右に順に実行し,それらの値を破棄する。最後のformの実行が正常に終了
した場合,tagbody形式は,nilを返す。
一連のtagbody-tag及びformは,まとめてtagbody形式の本体(又は,タグ本体)と呼ぶ。この本体の最
上位に現れる識別子tagbody-tagは,goによって本体内のその位置に制御を移すために使われるタグ本体
のタグ (tagbody tag) を表す。本体の最上位に現れる複合形式は,すべてformとして扱われる。リテラル
が,タグ本体の最上位にあってはならない。同一のtagbody-tagが,本体内のタグとして2回以上現れては
ならない。
タグ本体のタグに使用される名前空間は,ブロックの名前空間とは異なる。
タグ本体に静的に含まれる任意の位置で,評価形式 (go tag) は,静的原理(3.1参照)によって遮へい
される場合を除いて,タグtagに一致するtagbody-tagに制御を移すために使うことができる。
tagbodyによって設定されたタグは静的有効範囲をもつが,それが表すプログラム内の位置は,動的存在
期間をもつ。tagbodyの実行が終了した後は,goを使ってその本体内のタグ位置に制御を移行してはなら
ない。
本体のどの要素がtagbody-tagであるか,また,どれがformであるかの決定は,その要素のマクロ展開
よりも先に行われる。formがマクロ形式で,かつ,そのマクロ展開結果が記号又はリテラルである場合,
展開結果はtagbody-tagではなく,formとして扱われる。
タグ本体のタグが識別子以外である場合は,違反とする。その他のエラーについては,6.7.2参照。
備考 利用者が日常のプログラム開発でtagbody及びgoを使用することは望ましくない。これらの評
価形式の主な用法は,(マクロを使った)他の制御機能を実装する場合及び,実世界で時に必要
となる(有限状態機械のような)構造化されていない命令型の制御移動を実装する場合である。
例 (defmacro with-retry (:rest forms)
(let ((tag (gensym)))
ʻ(block ,tag
(tagbody
,tag
(return-from ,tag
(flet ((retry () (go ,tag)))
,@forms))))))
⇒ with-retry
(let ((i -5))
(with-retry
;; if-errorは,仮想的なエラー修正関数であり,
;; ISLISPでは定義していない。
36
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(if-error (sqrt (setq i(+ i 4)))
(retry))))
⇒ 1.7320508075688772
6.7.2
非局所的脱出におけるデータ整合性の保証
(unwind-protect form cleanup-form*) →<object>
特殊演算子
unwind-protectは,まずformを評価する。cleanup-form*は,formの評価が正常に終了するか又は非局所
的脱出によって終了するかにかかわらず,常に評価される。
formが正常に終了し,値Rを返した場合,すべてのcleanup-formが正常に終了したときには,値Rが
unwind-protectから返される。
formからの非局所的脱出が発生した場合,cleanup-form*が脱出の一部として実行される。この場合,す
べてのcleanup-formが正常に終了すれば,元の非局所的脱出が継続して実行される。
cleanup-form*は左から右に順に評価され,それらの値は破棄される。cleanup-form*の評価が正常に終了
した場合,unwind-protectからの脱出は上のとおり実行される。cleanup-formは,次の制約のもとに
unwind-protectからの非局所的脱出を行ってもよい。
unwmd-protect形式のcleanup-form*の実行中に,既に進行中の他の非局所的脱出によって無効となった脱
出先への非局所的脱出を実行した場合は,エラーが発生する(エラー名control-error)。
備考 ISLISPは対話型デバッガを規定していないので,プログラムによるエラー処理が失敗した場合
にエラー回復が対話的に行われるか,またどのように行われるかは規定しない。しかし,ISLISP
処理系が異常停止しなければ,非局所的脱出の機構(return-from,throw又はgo)が必要に応じ
て使われ,cleanup-formが実行される。
例 (defun foo (x)
(catch ʼduplicates
(unwind-protect (bar x)
(for ((1 x (cdr 1)))
((null 1) ʼunused)
(remove-property (car 1) ʼlabel)))))
⇒ foo
(defun bar (1)
(cond ((and (symbolp 1) (property 1 ʼlabel))
(throw ʼduplicates ʼfound))
((symbolp 1) (setf (property 1 ʼlabel) t))
((bar (car 1)) (bar (cdr 1)))
(t nil)))
⇒ bar
(foo ʼ(a b c))
⇒ t
(property ʼa ʼlabel)
⇒ nil
(foo ʼ(a b a c))
⇒ found
(property ʼa ʼlabel)
⇒ nil
(defun test ()
37
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(catch ʼouter (test 2)))
⇒ test
(defun test2 ()
(block inner
(test3 (lambda () (return-from inner 7)))))
⇒ test2
(defun test3 (fun)
(unwind-protect (test4) (funcall fun)))
⇒ test3
(defun test4 ()
(throw ʼouter 6))
⇒ test4
(test)
エラーが発生する。
このtestの例では,test4内で実行されたthrowの脱出先は,test内のcatch形式である。test3に
おけるunwind-protectは,制御の移行を横取りし,test2におけるblockからのreturn-fromを実行
しようとする。このblockは,脱出先であるcatch形式の動的存在期間内で設定されているので,
エラーが通知される。
7. オブジェクト指向機能
7.1
クラスの定義 defclass定義形式は,新しい名前付きクラスを定義する。
クラス定義は,次のものを含む。
・ 新しいクラスの名前。
・ 新しいクラスの直接の上位クラスのリスト。
・ スロット指定 (slot specifier) の集合。それぞれのスロット指定は,そのスロットの名前及び0個以上
のスロット任意機能 (slot option) を含む。一つのスロット任意機能は,一つのスロットだけに対する
指示とする。クラス定義は,同じ名前のスロット指定を二つ以上含んではならない。
・ クラス任意機能 (class option) の集合。それぞれのクラス任意機能は,そのクラス全体に対する指示と
する。
defclass定義形式のスロット任意機能及びクラス任意機能は,次の機構を提供する。
・ スロットの初期値を与える評価形式を指定する機構。インスタンス生成時に,そのスロットの初期値
が明示的に与えられなかった場合は,スロット任意機能で指定した評価形式の値が初期値となる。
・ スロットの値を取り出すメソッド,スロットに値を格納するメソッド及びスロットに値が束縛されて
いるどうかを判定するメソッドが,自動的に生成されることを要求する機構。
・ そのクラスのメタクラスを指定する機構。
・ そのクラスが抽象クラスであるかどうかを指定する機構。
(defclass class-name (sc-name*) (slot-spec*) class-opt*) →<symbol>
定義演算子
ここで,
class-name
::=
identifier
sc-name
::=
identifier
slot-spec
::=
slot-name | (slot-name slot-opt*)
slot-name
::=
identifier
38
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
slot-opt
::=
: reader reader-function-name |
: writer writer-function-name |
: accessor reader-function-name |
: boundp boundp-function-name |
: initform form |
: initarg initarg-name
reader-function-name
::=
identifier
writer-function-name
::=
identifier
boundp-function-name
::=
identifier
initarg-name
::=
identifier
class-opt
::=
(: metaclass metaclass-name) |
(: abstractp abstract-flag)
metaclass-name
::=
identifier
obstract-flag
::=
t | nil
defclass定義形式は,実行結果としてclass-nameという名前の記号を返す。
引数class-nameは識別子であり,新しいクラスの名前となる。class-nameの定義位置は,defclass定義形
式の直後とする。
引数sc-nameのそれぞれは,識別子であり,新しいクラスの直接の上位クラスを指定する。新しいクラ
スは,それぞれの上位クラスからスロットを継承し,スロットの : reader,: writer,: accessor及び : boundp
メソッドを継承する。スロットの継承方法は7.1.3において,メソッドの継承方法は7.2.3において規定す
る。同じsc-nameが,上位クラス名として2回以上現れてはならない。sc-nameのうちのいずれか二つが,
<standard-object>及び<object>以外の上位クラスを共通にもつ場合は,違反とする。ただし,<standard-class>
以外のメタクラスが指定された場合を除く。
引数slot-specのそれぞれは,スロットの名前か又はスロット名の後に0個以上のスロット任意機能を伴
ったリストとする。引数slot-nameは,識別子でなければならない。同じスロット名が,二つ以上のslot-spec
に現れてはならない。
次のスロット任意機能が使用できる。
・ : reader任意機能は,そのスロットの値を取り出すために,パラメタ記述 ((x class-name)) を伴った修
飾なしメソッドを,reader-function-nameという名前の包括関数に対して定義することを指示する。引
数reader-function-nameは,識別子でなければならない。: reader任意機能は,一つのスロットに対して
複数回指定してもよい。
・ : writer任意機能は,そのスロットに値を格納するために,パラメタ記述 ((y <object>) (x class-name)) を
伴った修飾なしメソッドを,writer-function-nameという名前の包括関数に対して定義することを指示
する。引数wirter-function-nameは,識別子でなければならない。: writer任意機能は,一つのスロット
に対して複数回指定してもよい。
・ : accessor任意機能は,そのスロットの値を取り出すために,パラメタ記述 ((x class-name)) を伴った
修飾なしメソッドを,reader-function-nameという名前の包括関数に対して定義することを指示する。
さらに,次のような包括関数を(もしなければ)定義する。その包括関数を,第1引数をy,第2引
数をxとして呼び出すことと, (setf (reader-function-name x) y) とが同値となる。その包括関数に対し,
パラメタ記述 ((y <object>) (x class-name)) を伴ったメソッドが定義される。引数reader-function-name
39
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
は,識別子でなければならない。: accessor任意機能は,一つのスロットに対して複数回指定してもよ
い。
・ : boundp任意機能は,そのスロットが既に束縛されているかどうかを判定するために,パラメタ記述
((x class-name)) を伴った修飾なしメソッドを,boundp-function-nameという名前の包括関数に対して定
義することを指示する。引数boundp-function-nameは,識別子でなければならない。: boundp任意機能
は,一つのスロットに対して複数回指定してもよい。
・ : initform任意機能は,そのスロットの初期化時に用いられる省略時初期値形式 (default initial value
form) を指定する。この任意機能は,一つのスロットに対して高々1回しか指定してはならない。こ
の初期値形式は,スロットを初期化するたびに評価される。スロットの初期化に用いられる識別子の
静的有効範囲は,defclass形式中におけるそれらの識別子の静的有効範囲とする。静的有効範囲は,変
数識別子及び関数識別子の両方に対して適用される。一方,現在の動的束縛としては,create(7.4.1
参照)の実行中に存在しているものが用いられる。
・ : initarg任意機能は,initarg-nameという名前の初期化引数 (initialization argument) を宣言し,この初
期化引数がそのスロットを初期化することを指定する。initialize-objectに渡された初期化リスト(7.4
参照)が,初期化引数及びそれに付随する値を含む場合は,その値が,スロットに格納される。この
場合,スロットに : initform任意機能が指定されていても,省略時初期値形式は,評価されない。初
期化リストがそのような初期化引数を含まない場合,: initform任意機能が指定されていれば,それに
従ってスロットが初期化される。初期化リストが,同じスロットに対する複数の初期化引数を含む場
合は,結果は未定義とする。詳細については,7.4.1による。: initarg任意機能は,同じスロットに対
して複数回指定してもよい。
: reader,: writer及び : accessorのスロット任意機能によって生成されたメソッドを,それぞれ: readerメ
ソッド,: writerメソッド及び: accessorメソッドと呼び,これらのメソッドが属する包括関数をスロットア
クセス関数 (slot accessor) と呼ぶ。: boundp任意機能によって生成されたメソッドを: boundpメソッドと呼
ぶ。
処理系は, (slot-name form) が (slot-name : initform form) の省略形となるようにdefclassの構文を拡張し
てはならない。
引数class-optは,クラス任意機能を指定する。これは,クラス全体に対する指示とする。次のクラス任
意機能が使用できる。
・ : metaclass任意機能は,定義しようとしているクラスが,システムの提供する省略時のメタクラス
<standard-class>とは異なるメタクラスをもつことを指示する。引数metaclass-nameは,メタクラスの
名前とする。: metaclass任意機能は,高々1回しか指定してはならない。<built-in-class>がメタクラス
として指定された場合は,違反とする。
・ : abstractp任意機能は,そのクラスが抽象クラスかどうかを指示する。この任意機能が指定され,かつ
abstract-flagがtの場合,このクラスの直接インスタンスを生成しようとしたとき,createがエラーを
通知する。この任意機能が指定されない場合又はabstract-flagがnilの場合,そのクラスは,抽象クラ
スではない。t及びnil以外のabstract-flagが指定された場合は,違反とする。
標準クラスにおいては,defclassに関して次の規則が成り立たなければならない。
・ defclass定義形式は,それが参照する上位クラス識別子の有効範囲内になければならない。
・ クラスは,そのインスタンスが生成される前に定義されていなければならない。
・ defmethod形式の中で,パラメタ特殊化指定としてclass-nameを使用する場合,そのdefmethod形式は,
40
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
class-nameの有効範囲内になければならない。すなわち,クラスの名前を用いるdefmethod形式は,
そのクラスを定義するdefclass形式よりもテキスト上で後になければならない。
ISLISP処理系を,これらの規則に適合しない状況にも対処できるように拡張してもよい。そのような拡
張は,処理系定義とする。
スロット任意機能は,上位クラスから下位クラスへ継承されたり,別のスロット記述によって遮へい又
は変更されることがある。しかし,クラス任意機能は,継承されない。スロット及びスロット任意機能の
継承については,7.1.3による。
スロットにスロットアクセス関数が指定されていない場合,そのスロットにはアクセスできない。
クラスを定義する場合,その定義形式の中で,直接の上位クラスを指定する順序が重要となる。新しい
クラスは,局所的優先順位 (local precedence order) をもつ。これは,クラスが並べられたリストであり,
その順序は,最初にその新しいクラス,次に直接の上位クラスをそのdefclass定義形式に指定された順序
で並べたものとする。
7.1.1
クラス優先度リストの決定 クラスCのクラス優先度リスト (class precedence list) とは,C及びそ
のすべての上位クラスに関する全順序であり,C及びその上位クラスの局所的優先順位と矛盾しないもの
とする。すなわち,それぞれの局所的優先順位の中に現れるクラスは,クラス優先度リストの中に同じ順
序で現れるものとする。
C1,...,Cnを,Cの直接の上位クラスとする。C1,...,Cnは,この順序でCのdefclass定義形式に指定
されているとする。C1,...,Cnのクラス優先度リストを,それぞれP1,...,Pnとする。P○Qを,クラス優
先度リストPとQとを連結したリスト又はクラス優先度リストQの先頭にクラスPを追加したリストと
定義する。このとき,Cのクラス優先度リストは,C○P1○...○Pnから,重複を除去したリストとする。連結
結果のリストに,あるクラスが2回現れた場合には,その左側を除去する。
標準クラスを定義するとき,その直接の上位クラスのもつクラス優先度リストの間に,<standard-object>
及び<object>以外のクラスが共通に含まれている場合は,違反とする。
7.1.2
スロットのアクセス defclass定義形式によって生成又は変更されたスロットアクセス関数を用い
て,スロットをアクセスできる。
defclass定義形式には,スロット値の取出し及び格納を行うメソッドを生成するための任意機能を指定で
きる。: reader任意機能を指定した場合,スロットの値を取り出すメソッドが自動的に生成される。ただし,
値を格納するメソッドは生成されない。: writer任意機能を指定した場合,スロットに値を格納するメソッ
ドが自動的に生成される。ただし,値を取り出すメソッドは生成されない。: accessor任意機能を指定した
場合,スロットの値を取り出すメソッド及び値を格納するメソッドが自動的に生成される。
: reader又は : writer任意機能をスロットに指定する場合,生成されるメソッドが属する包括関数の名前
を,直接指定する。: writer任意機能に対して指定した名前が識別子nameの場合,スロットへ値を格納す
るための包括関数の名前は識別子nameであり,この包括関数は,新しい値及びインスタンスという二つ
の引数をこの順序で受け取る。: accessor任意機能に対して指定した名前が識別子nameの場合,スロット
値を取り出す包括関数の名前は識別子nameであり,スロットへの値の格納は, (setf (name instance)
new-value)という構文によって行われる。ここで,instanceはそのスロットをもつインスタンスとし,
new-valueは新しい値とする。
: reader,: writer,: accessor及び : boundpの任意機能を指定することによって生成又は変更される包括関
数は,<standard-generic-function>の直接インスタンスとする。
41
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
7.1.3
スロット及びスロット任意機能の継承 クラスCのインスタンス中でアクセス可能なすべてのス
ロット名の集合は,C及びその上位クラスで定義されたスロット名の和集合とする。インスタンスの構造
(structure) とは,そのインスタンス中のすべてのスロット名の集合とする。
最も単純な場合,ある名前のスロットは,C又はその上位クラスのいずれか一つのクラスだけで定義さ
れている。スロットがCの上位クラスで定義されている場合,そのスロットは,継承 (inherit) されている
という。そのスロットの特性は,それを定義しているクラスのスロット指定によって決定される。
一般的には,C及びその上位クラスの複数のクラスにおいて,同じ名前のスロットが定義されている可
能性がある。その場合,その名前のただ一つのスロットだけが,Cのインスタンス中でアクセス可能とな
り,そのスロットの特性は,幾つかのスロット指定を次の規則に従って組み合せることによって決定され
る。
・ あるスロット名に対するすべてのスロット指定は,Cのクラス優先度リスト中の順序に従って,優先
度の高い指定から低い指定の順に並べられる。次で用いるスロット指定の優先度とは,この順序を意
味する。
・ スロットの省略時初期値形式は,: initform任意機能を含むスロット指定のうちで最も優先度の高いス
ロット指定に与えられた省略時初期値形式とする。いずれのスロット指定も: initform任意機能を含ま
ない場合は,そのスロットは省略時初期値形式をもたない。
・ スロットの初期化引数は,: initarg任意機能を含むスロット指定に与えられたすべての初期化引数の和
集合とする。いずれのスロット指定も: initarg任意機能を含まない場合は,そのスロットは初期化引数
をもたない。
: reader,: writer,: accessor及び : boundp任意機能は,メソッドを生成するのであって,スロットの特性
を定義するのではない。これらによって生成されるメソッドは,7.2.3で規定する意味で,継承される。
7.2
包括関数 包括関数 (generic function) は,呼び出されたときの振る舞いが,引数のクラスによって
決定される。包括関数オブジェクトは,メソッドの集合,ラムダリスト,メソッド組合せの方法及びその
他の情報からなる。メソッドは,包括関数のクラスごとの振る舞い及び操作を定義する。このため,メソ
ッドは,包括関数を特殊化 (specialize) するという。包括関数は,呼び出されると,引数のクラスに基づ
いてメソッド集合の部分集合を実行する。
包括関数は,通常の関数と同様に使用できる。
メソッド (method) は,メソッドの本体,そのメソッドがいつ適用可能かを指定するパラメタ特殊化指
定 (parameter specializer) を含むパラメタ記述の並び,及びメソッド組合せ機能がメソッドを区別するため
に用いる修飾子 (qualifier) の並びからなる。メソッドのそれぞれの必すパラメタは,付随するパラメタ特
殊化指定をもち,それらのパラメタ特殊化指定を満たす引数に対してそのメソッドが起動される。
メソッド組合せ機能は,メソッドの選択,それらを起動する順序及び包括関数の返す値を制御する。
ISLISPでは,標準的なメソッド組合せ方法は定義するが,メソッド組合せの新しい方法を定義するための
機能は規定しない。
通常の関数と同様に,包括関数も引数を受け取り,一連の操作を実行し,値を返す。通常の関数は,そ
れが呼び出されたときに必ず実行される本体のコードをただ一つもつ。包括関数は,本体コードの集合を
もち,その中から空でない部分集合が選択されて実行される。包括関数への引数のクラス及びそのメソッ
ド組合せ方法が,本体コードの選択方法及びそれらの組合せ方法を決定する。
(generic-function-p obj) →真偽値
関数
42
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数generic-function-pは,objが包括関数である場合はtを返し,それ以外の場合はnilを返す。objは,
いかなるISLISPオブジェクトでもよい。
7.2.1
包括関数の定義 包括関数を明示的に定義するには,defgeneric形式を使用する。defgeneric形式に
は,メソッド組合せの方法などの,包括関数の特性を指定することができる。また,: reader,: writer,: accessor
及び : boundp任意機能によって,defclass形式が暗黙のうちに包括関数を定義することができる。
包括関数に対してメソッドを定義する評価形式は,メソッド定義形式 (method-defining form) と呼ばれ,
これにはdefmethod形式及びdefclass形式がある。メソッドは,defgeneric形式によっても定義できるが,
この規格では,defgeneric形式はメソッド定義形式に含めない。
実行準備においては,defmethod形式は,特殊化しようとする包括関数のdefgeneric形式より後になけれ
ばならない。ただし,defclass形式が定義する : readerメソッド,: writerメソッド,: accessorメソッド及
び : boundpメソッドに対しては,対応する包括関数を定義するdefgeneric形式を与える必要はない。
(defgeneric func-spec lambda-list {option | method-desc}*) →<object>
定義演算子
ここで,
func-spec
::=
identifier | (setf identifier)
lambda-list
::=
(var* [&rest var]) |
(var* [: rest var])
option
::=
(: method-combination {identifier | keyword}) |
(: generic-function-class class-name)
method-desc
::=
(: method method-qualifier* parameter-profile form*)
method-qualifier
::=
identifier | keyword
parameter-profile
::=
({var | (var parameter-specializer-name)}* [{&rest | : rest} var])
parameter-specializer-name
::=
class-name
class-name
::=
identifier
var
::=
identifier
defgeneric形式は,包括関数を定義するために用いる。この定義形式は,包括関数名func-specを返す。
包括関数名func-specにおける識別子identifierの有効範囲は,最上位有効範囲全体とする。
引数lambda-listは,4.7による。
引数optionは,次のいずれかの任意機能とする。それぞれの任意機能は,高々1回しか指定してはなら
ない。
・ : method-combination任意機能は,メソッド組合せ方法の名前である記号又はキーワードを指定する。
組込みのメソッド組合せ方法の名前には,nil及びstandardがある。
・ : generic-function-class任意機能は,システムの提供する省略時クラス<standard-generic-function>以外の
クラスに包括関数が属することを指定する。引数class-nameは,包括関数のクラスになりうるクラス
の名前とする。
引数method-descは,メソッド記述 (method description) と呼ばれ,包括関数に属するメソッドを,
defmethodによって定義したかのように定義する。メソッド記述中の引数method-qualifier及び
parameter-profileは,defmethodのそれと同じとする。引数form*は,メソッドの本体を指定する。
メソッド記述が指定されない場合,メソッドをもたない包括関数が生成される。包括関数が呼び出され,
適用するメソッドがない場合は,エラーが発生する。
43
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
defgenericの引数lambda-listは,この包括関数に対するメソッドのパラメタ記述の形を指定する。包括
関数のすべてのメソッドは,このlambda-listと合同なパラメタ記述をもたなければならない。ここでの合
同の定義は,7.2.2.2による。
処理系は,これ以外に,処理系定義の任意機能を含むようにdefgenericを拡張してもよい。
7.2.2
包括関数に対するメソッド定義
(defmethod func-spec method-qualifier* parameter-profile form*) →<object>
定義演算子
ここで,
func-spec
::=
identifier | (setf identifier)
method-qualifier
::=
identifier | keyword
parameter-profile
::=
({var | (var parameter-specializer-name)}* [{&rest | : rest} var])
parameter-specializer-name
::=
class-name
class-name
::=
identifier
var
::=
identifier
defmethod定義形式は,包括関数のメソッドを定義し,包括関数名func-specを返す。
メソッド定義形式は,包括関数に対する引数によってそのメソッドが起動されたときに,実行すべきコ
ードを含む。
メソッド定義形式の実行準備によって,次のいずれかが起こる。
・ func-specが既存の包括関数の名前であり,この包括関数がパラメタ特殊化指定及び修飾子に関して,
新たに定義しようとしているメソッドと合致するメソッドを含んでいる場合は,違反とする。パラメ
タ特殊化指定及び修飾子の合致の定義は,7.2.2.1による。
・ func-specが既存の包括関数の名前であり,この包括関数がパラメタ特殊化指定及び修飾子に関して新
たに定義しようとしているメソッドと合致するメソッドを含まない場合,新しいメソッドがこの包括
関数に追加される。
・ defmethod定義形式が,包括関数でない関数の名前func-specの有効範囲に入っている場合は,違反と
する。
・ func-specという名前の包括関数が,最上位有効範囲で定義されていない場合は,違反とする。さらに,
func-specに対するdefgeneric形式が,実行準備しようとしているそのテキスト上で,メソッド定義形
式よりも前にない場合は,違反とする。ただし,そのメソッド定義形式がdefclassである場合を除く。
定義されるメソッドのパラメタ記述は,包括関数のラムダリストと合同でなければならない。ここでの
合同の定義は,7.2.2.2による。
引数method-qualifierは,メソッド修飾子と呼ばれ,メソッド組合せは,これをメソッドに対する属性と
して用いる。メソッド修飾子は,nil以外の記号又はキーワードとする。メソッド修飾子として許されるも
のは,包括関数のメソッド組合せ方法によって,更に制限される。単純メソッド組合せ方法の場合は,修
飾なしメソッドだけが許される。標準メソッド組合せ方法の場合は,修飾なしメソッド,又は: before,: after
及び: aroundのキーワードのうちのいずれか一つだけを修飾子としてもつメソッドが許される。
引数parameter-profileは,パラメタ記述 (parameter profile) と呼ばれ,通常の関数のラムダリストと似て
いるが,必すパラメタの名前を特殊化されたパラメタ (specialized parameter) で置き換えられる点が異なる。
特殊化されたパラメタとは, (var parameter-specializer-name) の形のリストとする。必すパラメタだけが
特殊化できる。パラメタ特殊化指定の名前parameter-specializer-nameは,クラス名を表す識別子とする。
44
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
必すパラメタに対して,パラメタ特殊化指定名が指定されていない場合,パラメタ特殊化指定として,識
別子<object>が省略されたものとする。
引数form*は,メソッドの本体を指定する。
パラメタ特殊化指定及び修飾子に関して合致する二つのメソッドを,同じ包括関数に対して定義しては
ならない。ここでの合致の定義は,7.2.2.1による。
メソッドは関数ではなく,関数として呼び出すことはできない。
7.2.2.1
パラメタ特殊化指定及び修飾子に関する合致 次の条件がすべて成り立つとき,二つのメソッド
は,パラメタ特殊化指定及び修飾子に関して合致するという。
a) 二つのメソッドが,同じ個数の必すパラメタをもつ。ここで,二つのメソッドのパラメタ特殊化指定
を,P1,...,Pn及びQ1,...,Qnとする。
b) 1≤i≤nであるすべてのiについてPiとQiとが合致する。パラメタ特殊化指定PiとQiとは,それぞれ
が同じクラスを指す場合に合致する。それ以外の場合,PiとQiとは合致しない。
c) 両方のメソッドに修飾子がある場合に,それらが一致する。
ここで,パラメタ特殊化指定は,パラメタ記述から得られる(defmethod参照)。
7.2.2.2
包括関数のラムダリストとメソッドのパラメタ記述との合同 ある包括関数のラムダリストと
そのメソッドのパラメタ記述とは,次の二つの条件を満たすときに合同であるという。
a) 両方が,同じ個数の必すパラメタをもつ。
b) 一方が&rest又は : restを含む場合,他方も&rest又は : restを含む。
7.2.3
メソッドの継承 下位クラスは,次の意味でメソッドを継承する。あるクラスのすべてのインスタ
ンスに対して適用可能なメソッドは,そのクラスの下位クラスのすべてのインスタンスに対しても適用可
能となる。下位クラスのインスタンスは,上位クラスのインスタンスでもあるからである。
メソッドは,それがdefmethod形式によって生成されたものか,defclass形式の任意機能によって自動生
成されたものかに関係なく,全く同様に継承される。
7.3
包括関数の呼出し 包括関数がある引数とともに呼び出されると,まず実行するコードを決定する。
このコードは,与えられた引数に対する実効メソッド (effective method) と呼ばれる。実効メソッドは,そ
の包括関数中の適用可能メソッドの一部又はすべての組合せとする。包括関数が呼び出され,適用可能な
メソッドがない場合は,エラーが発生する。
実効メソッドが決定されると,包括関数に渡された引数がそのまま渡されて実効メソッドが起動される。
それが返す値が,包括関数の値として返される。
実効メソッドは,次の3段階の手続によって決定される。
a) 適用可能なメソッドを選択する。
b) 適用可能なメソッドを,優先順位に従って,優先度の高いメソッドから低いメソッドの順に並べる。
c) 適用可能なメソッドを,メソッド組合せ方法に従って適用する。
7.3.1
適用可能なメソッドの選択 ある包括関数及びそれへの引数が与えられたとき,適用可能なメソッ
ド (applicable method) とは,その包括関数のメソッドであり,そのすべてのパラメタ特殊化指定が対応す
る引数によって満たされるメソッドとする。メソッドが適用可能であること及び引数がパラメタ特殊化指
定を満たすことの定義を次に示す。
A1,...,Anを,包括関数への必すパラメタに対応する引数とする。P1,...,Pnを,メソッドMの必すパ
ラメタに対応するパラメタ特殊化指定とする。すべてのAiがPiを満たす (satisfy) とき,メソッドMは適
用可能 (applicable) であるという。AiがクラスCの直接インスタンスとするとき,CがPi及びその下位ク
45
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
ラスのいずれかである場合に,AiはPiを満たすという。
すべてのパラメタ特殊化指定がクラス<object>となっているメソッドを,省略時メソッド (default
method) と呼ぶ。これは常に適用可能なメソッドであるが,優先度の高いメソッドによって遮へいされる
ことがある。
メソッドは修飾子 (qualifier) をもっことができ,これによってメソッド組合せの際に,メソッドを区別
することができる。一つ以上の修飾子をもつメソッドを,修飾付きメソッド (qualified method) と呼ぶ。修
飾子をもたないメソッドを,修飾なしメソッド (unqualified method) と呼ぶ。
7.3.2
適用可能メソッドの優先順位 二つのメソッドの優先順位を決定するために,それらのパラメタ特
殊化指定が左から右に順に比較される。
二つのメソッドの,対応するパラメタ特殊化指定が比較される。パラメタ特殊化指定が等しい場合は,
その次が比較される。すべての対応するパラメタ特殊化指定が等しい場合,二つのメソッドは異なる修飾
子をもつはずなので,修飾子を比較することによって,それらのメソッド間に優先順位をつけることがで
きる。
ある対応するパラメタ特殊化指定が等しくなかった場合,それらに対応する引数のクラスのクラス優先
度リストを調べ,その中に先に現れるパラメタ特殊化指定をもつメソッドを,優先度の高いメソッドとす
る。そのクラス優先度リストに,両方のパラメタ特殊化指定が現れることは,適用可能なメソッドの選択
方法が保証する。
この結果として生成される適用可能メソッドのリストは,優先度の最も高いメソッドが最初に,最も低
いメソッドが最後に現れる。
7.3.3
メソッドの適用 一般的に,実効メソッドは,適用可能メソッドの組合せとなる。実効メソッドは,
適用可能メソッドの一部又はすべてを呼び出し,包括関数の値となる値を返す。また,幾つかのメソッド
がcall-next-methodによってアクセスできるようにする。実効メソッドの本体とは,これらを行う評価形式
であり,これに適切なラムダリストが付加され,関数となる。
実効メソッドの中の各メソッドの役割は,そのメソッド修飾子及びメソッドの優先順位によって決定さ
れる。メソッド修飾子は,メソッドに対する印であり,修飾子の意味は,メソッド組合せの際にこれらの
印がどのように用いられるかによって決まる。適用可能メソッドが,メソッド組合せ方法が認識できない
修飾子をもつ場合は,エラーが発生する。
ISLISPには,二つのメソッド組合せ方法がある。defgeneric形式の: method-combination任意機能に対し
て,nil又はstandardを指定することによって,どちらのメソッド組合せ方法を使うかを指定できる。
7.3.3.1
単純メソッド組合せ メソッド組合せ方法の名前がnilの場合は,単純メソッド組合せ (simple
method combination) が使用される。この場合,実効メソッドは,すべての適用可能メソッドのうち,最も
優先度の高いメソッドを呼び出す。呼び出されたメソッドでは,優先度が次に最も高いメソッドを
call-next-methodを用いて呼び出すことができる。call-next-methodが呼び出すメソッドを,次メソッド (next
method) と呼ぶ。述語next-method-pは,次メソッドの有無を判定する。call-next-methodが呼び出され,次
メソッドが存在しない場合は,エラーが発生する。
7.3.3.2
標準メソッド組合せ メソッド組合せ方法が指定されていない場合,又はメソッド組合せ方法の
名前としてstandardが指定された場合は,標準メソッド組合せ (standard method combination) が用いられる。
主メソッド (primary method) は,実効メソッドの主要な動作を定義する。補助メソッド (auxiliary
method) は,主メソッドの動作を3通りの方法で修正する。主メソッドとはメソッド修飾子をもたないメ
ソッドとし,補助メソッドとはメソッド修飾子が: before,: after又は: aroundのいずれかであるメソッドと
46
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
する。
・ : beforeメソッドとは,キーワード: beforeを修飾子としてもつメソッドとする。: beforeメソッドは,
主メソッドの前に実行されるコードを指定する。
・ : afterメソッドとは,キーワード: afterを修飾子としてもつメソッドとする。: afterメソッドは,主メ
ソッドの後に実行されるコードを指定する。
・ : aroundメソッドは,キーワード: aroundを修飾子としてもつメソッドとする。: aroundメソッドは,
他の適用可能メソッドの代わりに実行されるコードを指定するが,それらの適用可能メソッドを起動
することもできる。
標準メソッド組合せの意味は,次のとおりとする。
・ : aroundメソッドがある場合,最も優先度の高い: aroundメソッドが呼び出される。このメソッドの値
が包括関数の値となる。
・ : aroundメソッドの本体の中では,call-next-methodを用いて次メソッドを呼び出すことができる。次
メソッドが戻ると,: aroundメソッドは,その返り値に基づいて更にコードを実行できる。
call-next-methodが使用されたとき,適用可能なメソッドがない場合は,エラーが発生する。
next-method-pを用いて,次メソッドの有無を判定できる。
・ : aroundメソッドがcall-next-methodを起動した場合,優先度が次に最も高い: aroundメソッドが適用可
能であれば,それが呼び出される。: aroundメソッドがない場合,又は最も優先度の低い: aroundメソ
ッドからcall-next-methodが呼び出された場合,他のメソッドが次のように呼び出される。
・ すべての: beforeメソッドが,優先度の高いものから順に呼び出される。それらの返り値は無視される。
call-next-methodを: beforeメソッドの中で使用した場合は,エラーが発生する。
・ 最も優先度の高い主メソッドが呼び出される。その主メソッドの本体の中では,call-next-methodを用
いて,優先度が次に最も高い主メソッドを呼び出すことができる。そのメソッドが戻ると,元の主メ
ソッドは,その返り値に基づいて更にコードを実行できる。call-next-methodが使用され,適用可能な
主メソッドがそれ以上存在しない場合は,エラーが発生する。関数next-method-pを用いて,次メソッ
ドの有無を判定できる。call-next-methodが使用されない場合は,優先度の最も高い主メソッドだけが
呼び出される。
・ すべての: afterメソッドが,優先度の低いものから順に呼び出される。それらの返り値は無視される。
call-next-methodが:afterメソッドの中で使用された場合は,エラーが発生する。
・ : aroundメソッドが起動されなかった場合,優先度の最も高い主メソッドの値が包括関数の返す値と
なる。なお,優先度の最も低い: aroundメソッド中でのcall-next-methodの呼出しが返す値は,優先度
の最も高い主メソッドの返す値となる。
標準メソッド組合せを用いる場合,適用可能な主メソッドがない場合は,エラーが発生する。: beforeメ
ソッドは優先度の最も高いものから順に実行され,: afterメソッドは優先度の最も低いものから順に実行
される。この相違の理由を,例によって示す。クラスC1がその上位クラスC2の振る舞いを,: before及び:
afterメソッドを追加することで,変更したとする。クラスC2の振る舞いが,C2のメソッドによって直接
定義されているか上位クラスから継承されているかは,クラスC1のインスタンスに対するメソッド起動の
相対的順序に影響を与えない。クラスC1の: beforeメソッドは,クラスC2のすべてのメソッドよりも前に
実行される。クラスC1の: afterメソッドは,クラスC2のすべてのメソッドよりも後に実行される。
一方,すべての: aroundメソッドは,: aroundメソッド以外のどのメソッドよりも先に実行される。この
ため,より優先度の低い: aroundメソッドが,より優先度の高い主メソッドよりも先に実行される。
47
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
主メソッドだけが用いられ,かつcall-next-methodが用いられなかった場合,優先度の最も高い主メソッ
ドだけが起動される。つまり,優先度の高い主メソッドは,優先度の低い主メソッドを遮へいする。
7.3.4
次メソッド及びその呼出し
(call-next-method) →<object>
局所関数
関数call-next-methodは,メソッドの中で次メソッドを呼び出すために使われる。呼び出した次メソッド
の返り値が,この関数の値となる。call-next-methodが戻ると,その呼出し以降の計算を続けることができ
る。
どのメソッドがcall-next-methodを呼び出せるか,またどのメソッドが呼び出されるかは,メソッド組合
せの方法によって決定される。
単純メソッド組合せの場合,次メソッドとは,優先度が次に最も高いメソッドとする。
標準メソッド組合せ方法の場合,主メソッド及び: aroundメソッドの中で,call-next-methodを使うこと
ができる。このとき,次メソッドは,7.3.3.2で定義したとおりとする。
call-next-methodは,現在のメソッドに渡された引数をそのまま次メソッドに渡す。メソッドのパラメタ
に対してsetqを用いたり,パラメタと同じ名前の変数を再束縛しても,call-next-methodが渡す引数には影
響を与えない。
call-next-methodの関数束縛は,メソッドの本体における静的束縛とする。すなわち,labelsによって設
定されたかのように見える。この束縛の関数オブジェクトは,無制限の存在期間をもつ。
call-next-methodが,それを許さないメソッド中で使用された場合は,エラーが発生する。
call-next-methodが実行され,次メソッドがない場合は,エラーが発生する。
(next-method-p) →真偽値
局所関数
関数next-method-pは,メソッドの本体内で,次メソッドの有無を判定するために使われる。この関数は,
次メソッドが存在する場合はtを返し,それ以外の場合はnilを返す。
next-method-pの関数束縛は,メソッドの本体における静的束縛とする。すなわち,labelsによって設定
されたかのように見える。この束縛が参照する関数オブジェクトは,無制限の存在期間をもつ。
7.4
オブジェクトの生成及び初期化
(create class {initarg initval} *) →<object>
包括関数
関数createは,新しいオブジェクトを生成して返す。そのオブジェクトは,指定されたクラスのインス
タンスとする。第1引数は,クラスオブジェクトでなければならない。
新しいインスタンスの初期化は,インスタンスのための記憶領域の割当て,スロットへの値の設定,初
期化の追加処理のために利用者が与えたメソッドの実行,という手順からなる。第2と第3の手順は,
initialize-objectという包括関数によって実装されている。これによって,これらの手順を変更することが
可能となる。初期化引数 (initarg) とそれに付随する値 (initval) とが,交互に並んだ一つのリストとして,
initialize-objectに渡される。このリストを初期化リスト (initialization list) と呼ぶ。createは,initialize-object
が初期化した新しいインスタンスを返す。
7.4.1
インスタンスの初期化 createは,新しく生成したインスタンスを初期化するために,包括関数
initialize-objectを呼び出す。この包括関数は,標準メソッド組合せを用いる。initialize-objectには,利用者
定義のクラスに対するメソッドを定義できる。これによって,システムの提供するスロット設定機構を拡
張したり変更することが可能となる。
初期化においては,すべてのスロットが未束縛である新しいインスタンスが生成され,その後で
48
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
initialize-objectが呼び出される。
包括関数initialize-objectは,新しいインスタンス及び初期化リストを引数として,呼び出される。
initialize-objectは,システムが提供する主メソッドをもつ。このメソッドのパラメタ特殊化指定は,クラ
ス<standard-object>とする。このメソッドは,与えられた初期化リスト及び各スロットに対する: initform任
意機能に従って,次のとおりスロットを設定する。
・ そのスロットが既に値をもっていれば,その値は変更しない。
・ そのスロットに対する初期化引数と初期値との組が初期化リスト中にある場合,その初期値によって
スロットを初期化する。スロットに対する初期化引数の名前は,defclass中の: initarg任意機能によっ
て宣言される。
・ そのスロットが省略時初期値形式(defclass参照)をもつ場合,その評価形式が定義された静的環境及
び現在の動的環境の下で,それを評価する。評価の結果が,スロットの値となる。
・ 上のいずれでもない場合,スロットは初期化されない。
(initialize-object instance initialization-list) →<object>
包括関数
包括関数initialize-objectは,新しく生成されたインスタンスを初期化するためにcreateから呼び出され
る。包括関数initialize-objectは,新しいインスタンス及び初期化リストを引数とする。
initialize-objectに対しシステムが提供する主メソッドは,initialization-list及びスロットの: initform任意機
能に従って,インスタンスのスロットを初期化する。
引数instanceは,初期化されるインスタンスとする。初期化されたインスタンスが結果として返される。
利用者は,インスタンスの初期化時の動作を指定するため,initialize-objectに対してメソッドを定義でき
る。
: afterメソッドだけが定義された場合,それらのメソッドは,システムの提供する初期化用の主メソッ
ドの後に実行される。したがって,それらのメソッドは,initialize-objectの元々の動作に対して影響を与
えない。利用者がこの包括関数に対して定義した主メソッド又は: aroundメソッドがinstanceを返さない場
合は,結果は未定義とする。
7.5
クラスに関する問合せ
(class-of obj) →<class>
関数
関数class-ofは,与えられたobjを直接インスタンスとするクラスを返す。objは,いかなるISLISPオブ
ジェクトでもよい。
(instancep obj class) →真偽値
関数
関数instancepは,objがクラスclassの(直接あるいはそれ以外の)インスタンスである場合はtを返し,
それ以外の場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。classがクラスオブジェク
トでない場合は,エラーが発生する(エラー名domain-error)。
(subclassp class1 class2) →真偽値
関数
関数subclasspは,クラスclass1がクラスclass2の下位クラスである場合はtを返し,それ以外の場合は
nilを返す。class1又はclass2のいずれかがクラスオブジェクトでない場合は,エラーが発生する(エラー
名domain-error)。
(class class-name) →<class>
特殊演算子
この特殊形式は,class-nameという名前のクラスオブジェクトを返す。
49
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
8. マクロ マクロ機能は,言語を構文的に拡張する。マクロは,表層的変換を抽象化したものとする。
ISLISPテキスト(例えば,関数定義)は,内部的にはISLISPのオブジェクトによって表現できるので,
この表層的変換は,リスト処理によって記述できる。評価形式はコンス又は他のオブジェクトで表され,
個々のマクロはあるオブジェクトのグループから他のグループヘの変換関数を記述する。
マクロは,あるオブジェクトのグループから他のグループへの変換を実装する展開関数 (expander
function) によって内部的に定義される。展開関数の操作は,defmacro形式によって指定する。
展開関数は,引数として一つの評価形式を受け取り,異なる評価形式を値として返す。展開関数は主な
役割として,入れ子になったリスト集合を生成する。このために,逆引用符機能を用意している。
マクロは,実行準備時に展開される。いかなる実行時情報も使えない。使用可能な操作は,単純なデー
タ構造の生成及び処理に制限される。すなわち,(端末への入出力のような)環境への副作用,(記号の属
性リスト変更のような)外部的にアクセスできるデータ構造への副作用,及びマクロ形式自身への副作用
を引き起こす操作は禁止する。
マクロは,最上位でだけ定義できる。マクロは,再定義(すなわち,重複定義)してはならない。マク
ロは,実行準備の段階で,それを使用する前に定義しなければならない。
マクロ形式の展開結果は,他の評価形式となる。展開後の評価形式がマクロ形式である場合は,結果が
マクロ形式でなくなるまで展開される。
最上位形式がマクロ形式のとき,そのマクロ展開結果も,最上位形式とみなす。
マクロ形式は,setf形式の場所指定として使用できる(6.2のsetf参照)。
(defmacro macro-name lambda-list form*) →<symbol>
定義演算子
defmacro形式は,名前の付いたマクロを定義する。マクロ展開関数が呼び出されるとき,マクロ名をも
つ暗黙のブロックは生成されない。macro-nameは識別子であり,その有効範囲は,最上位有効範囲全体と
する。lambda-listの定義は,4.7による。macro-nameの定義位置は,lambda-listの直後とする。
例 (defmacro caar (x) (list 'car (list ʼcar x)))
⇒ caar
ʼform→<object>
構文
,form→<object>
構文
,@form→<object>
構文
これらの構文を,それぞれ逆引用符構文 (quasiquote syntax),非引用構文 (unquote syntax) 及び非引用連
結構文 (unquote-splicing syntax) と呼ぶ。
逆引用符構文は,リスト構造を作る。form内に非引用構文又は非引用連結構文のいずれも現れない場合,
逆引用符構文は,quote形式と同様に,引数を評価せずに返す。
非引用構文は,逆引用符構文内だけで有効とする。逆引用符構文内に現れた場合,非引用構文は,その
formを評価し,その結果を逆引用符構文内に非引用構文の代わりとして挿入する。
非引用連結構文も,逆引用符構文内だけで有効な構文とする。逆引用符構文内に現れた場合,非引用連
結構文は,そのformを評価する。評価結果は,リストでなければならない。このリストのすべての要素が,
上位リスト内に非引用連結構文の代わりとして挿入される。
逆引用符構文は入れ子にしてもよい。置換は,入れ子の“深さ”が同じである非引用構文又は非引用連
結構文に対してだけ行われる。入れ子の深さは,逆引用符構文に入ると一つ増加し,非引用構文又は非引
用連結構文に入ると一つ減少する。
50
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
例 ʻ(list ,(+ 1 2) 4)
⇒ (list 3 4)
(let ((name ʼa)) ʼ(list name ,name ʼ,name))
⇒ (list name a (quote a))
ʻ(a ,(+ 1 2) ,@(create-list 3 ʼx) b)
⇒ (a 3 x x x b)
ʻ((foo ʼ(- 10 3)) ,@(cdr ʼ(c)) . ,(car ʼ(cons)))
⇒ ((foo 7) . cons)
ʻ(a ʻ(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
⇒ (a ʼ(b , (+ 1 2) ,(foo 4 d) e) f)
(let((name1 ʼx)
(name2 ʼy))
ʻ(a ʻ(b ,,name1 ,ʼ,name2 d) e))
⇒ (a ʻ(b ,x ,ʼy d) e)
9. 宣言及び型変換
(the class-name form) →<object>
特殊演算子
(assure class-name form) →<object>
特殊演算子
これらの評価形式は,formを評価する。formが戻るならば,その返り値がthe形式又はassure形式の値
として返される。さらに,これらの評価形式は,formの値がclass-name(存在するクラスの名前でなけれ
ばならない。)によって示されたクラスのインスタンスであることを指定する。
the形式では,formの値がclass-nameによって指定されたクラス又はその下位クラスのインスタンスで
ない場合は,結果は未定義とする。assure形式では,formの値がclass-nameによって指定されたクラス又
はその下位クラスのインスタンスでない場合は,エラーが発生する(エラー名domain-error)。
例 (the <integer> 10)
⇒ 10
(the <number> 10)
⇒ 10
(the <float> 10)
結果は未定義とする。
(assure <integer> 10)
⇒ 10
(assure <number> 10)
⇒ 10
(assure <float> 10)
エラーが発生する。
(convert obj class-name) →<object>
特殊演算子
convertは,型変換関数 (coercion function) と呼ばれる次のいずれかに従って,オブジェクトobjに対応
するクラスclass-nameのオブジェクトを返す。表は最左列にobj,最上行にclass-nameを示す(クラス名
の<>は,この表では記述上の簡潔さのために省略する。)。
51
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
character
integer
float
symbol
string
general-vector
list
character
=
I
−
I(3)
−(4)
−
−
integer
I
=
X
−
X(5)
−
−
float
−
−(1)
=
−
X(6)
−
−
symbol
−
−
−
=
I(3)
−
−
string
−
X(2)
X(2)
I(3)
=
X(7)
X
general-vector
−
−
−
−
−
=
X
list
−
−
−
−
−
X
=
備考
= これは,恒等関数とする。
X
この型変換は,用意される。
X(2)
この型変換が試みられ,文字列が変換先クラスの数値のテキスト表現を含
まない場合は,エラーが発生する。その他すべての点において,これは
parse-numberと同じとする。
X(5)
これは,〜D書式指示と同じでよい。
X(6)
これは,〜G書式指示と同じでよい。
X(7)
これは,文字列が実装上ベクタであるならば恒等関数とする。
I
この型変換は用意されるが,その定義は処理系定義とする。
I(3)
この型変換は用意されるが,その定義は処理系定義とする。型変換は,処
理系におけるエスケープ不要の英文字(10.1.2参照)に依存する。
− この型変換を行おうとした場合は,エラーが発生する。
−(1)
この型変換を必要とする場合は,floor,ceiling,round又はtruncateのいず
れかの関数を代わりに使用すればよい。
−(4)
この型変換を必要とする場合は,代わりに (create-string 1 obj) を使用すれ
ばよい。
処理系が,処理系定義のクラスを用意している場合は,それらのクラス名に対して,convertを使用して
処理系定義の型変換を提供してもよい。
例 (convert 3 <float>)
⇒ 3.0
(convert "abc" <general-vector>)
⇒ # (#\a #\b #\c)
(convert #(a b) <list>)
⇒ (a b)
10. 記号クラス 記号は,クラス<symbol>のインスタンスとする。記号は,名前付き (named) でも名前な
し (unnamed) でもよい。記号の名前は,入出力時に記号を識別するために使用されることから,しばしば
印字名 (print name) と呼ばれる。記号は,属性 (property) をもつことができる。
(symbolp obj) →真偽値
関数
関数symbolpは,objが記号(クラス<symbol>のインスタンス)である場合はtを返し,それ以外の場合
はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (symbolp ʼa)
⇒ t
(symbolp "a" )
⇒ nil
(symbolp #\a)
⇒ nil
52
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(symbolp ʼt)
⇒ t
(symbolp t)
⇒ t
(symbolp ʼnil)
⇒ t
(symbolp nil)
⇒ t
(symbolp ʼ())
⇒ t
(symbolp ʼ*pi*)
⇒ t
(symbolp *pi*)
⇒ nil
10.1 記号名 記号は,名前付き (named) 又は名前なし (unnamed) のいずれかとする。
名前から記号への写像がある。異なる記号(eqが真でない記号)は,常に異なる名前をもつ。このよう
な写像は,名前なしの記号には定義されない。
記号の名前は,文字列として表現される。
10.1.1 記号の表記 記号の名前を構成する文字は,1.4による。
名前付き記号は,縦棒 (“|”) で囲まれた印字名で示される。しかし,記号が次の二つの条件を満たす
場合は,縦棒で囲む必要はない。
a) 記号の印字名が,エスケープ不要の英文字(10.1.2参照)又はそれらと次の追加文字だけからなると
き。
0 1 2 3 4 5 6 7 8 9 + - < > / * = ? ̲ ! $ % [ ] ^ { } 〜
(この集合は,処理系定義の追加の文字を含んでもよい。)
b) 記号の印字名の最初の文字が,通常の英文字か又は次の文字のとき。
< > / * = ? ̲ ! $ % [ ] ^ { } ~
(この集合は,処理系定義の追加文字を含んでもよい。)
さらに,次の記号は,縦棒で囲まなくてもよい。
+ - 1+ 1-
記号名が縦棒を含む場合は,縦棒の前に逆斜線 “\” を置かなければならない。記号名が逆斜線を含む
場合は,その逆斜線の前に別の逆斜線を置かなければならない。例えば, “|\\\\\|\\\||” は,逆
斜線,逆斜線,縦棒,逆斜線,縦棒という五つの文字からなる名前の記号を表す。
備考 すべての必すの記号は縦棒なしで書くことができる。
記号の名前が,コロン (:) 又はアンパサンド (&) を含み得るかどうかは処理系定義とする。したがって,
&rest,: rest及びその他のキーワード(例えば,: before)が,記号として表されるか又は何か別のものと
して表されるかは処理系定義とする。
10.1.2 記号名における大小文字 記号のテキスト表現が縦棒で囲まれていないとき,テキスト表現内の英
文字の大文字小文字の相違は無視される。したがって,次のテキスト表現は,同じ記号を表す。
foo foO fOo fOO Foo FoO FOo FOO
内部的には記号の印字名内の大文字小文字は保存され,区別される。例えば,|FOO|と|foo|とは,いかな
る処理系においても同じ記号ではない。しかし,入力機構は,名前が縦棒で囲まれていない記号に対して
は,大文字小文字を正規化する。したがって,fooとFOOとは,同じ記号を表すことになる。しかし,こ
の記号が|foo|又は|FOO|のどちらであるかは処理系定義とする。
各処理系は,英文字の変換方向 (neutral alphabetic case) と呼ばれる処理系定義の属性をもつ。これは,
“小文字へ”又は“大文字へ”のいずれかとする。英文字の変換方向が“小文字へ”である処理系の場合,
エスケープ不要の英文字 (neutral alphabetic character) は,次のとおりとする。
53
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
a b c d e f g h i j k l m n o p q r s t u v w x y z
そうでない場合(英文字の変換方向が“大文字へ”である処理系では),エスケープ不要の英文字は,次
のとおりとする。
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
英文字の変換方向が“小文字へ”である処理系の場合は,foo,FOO及び|foo|は同じ記号を表す。そうで
ない場合は,foo,FOO及び|FOO|が同じ記号を表す。
処理系は,エスケープ不要の英文字の集合に処理系定義の文字を追加してもよい。
10.1.3 nil及び() 記号nilは偽値及び空リストの両方を表し,()と表記してもよい。
10.2 記号属性 記号の属性 (property) は,属性名 (property name) と属性値 (property value) との間の名
前による関連付けとする。記号sに属性名pが関連付けられている場合,sは属性pをもつという。
(property symbol property-name [obj]) →<object>
関数
関数propertyは,記号symbolに関連付けられたproperty-nameという名前の属性の値を返す。symbolが
property-nameという名前の属性をもたなければ,obj(省略時値はnil)を返す。
symbol又はproperty-nameのいずれかが記号でない場合は,エラーが発生する(エラー名domain-error)。
objは,いかなるISLISPオブジェクトでもよい。
例 (property ʼzeus ʼdaughter)
⇒ athena
(setf (property symbol property-name) obj) →<object>
特殊形式
(set-property obj symbol property-name) →<object>
関数
これらは,objを記号symbolに関連付けられたproperty-nameという名前の属性の新しい値とする。
property-nameという名前の属性が既に存在するならば,それに対応する属性値を置き換える。そうでな
ければ,新しい属性を生成する。objを値として返す。
symbol又はproperty-nameのいずれかが記号でない場合は,エラーが発生する(エラー名domain-error)。
objは,いかなるISLISPオブジェクトでもよい。
例 (setf (property ʼzeus ʼdaughter) ʼathena)
⇒ athena
(set-property ʼathena ʼzeus ʼdaughter)
⇒ athena
(remove-property symbol property-name) →<object>
関数
関数remove-propertyは,記号symbolに関連付けられた属性property-nameを削除し,属性が存在する場
合は削除された属性の属性値を返す。そのような属性が存在しない場合は,nilを返す。
symbol又はproperty-nameのいずれかが記号でない場合は,エラーが発生する(エラー名domain-error)。
例 (remove-property ʼzeus ʼdaughter)
⇒ athena
10.3 名前なしの記号
(gensym) →<symbol>
関数
関数gensymは,名前なしの記号を生成して返す。gensymは,マクロを書くのに有用となる。名前なし
の記号は,識別子によって指定することはできない。
例 (defmacro twice (x)
(let ((v (gensym)))
ʻ(let((,v ,x)) (+ ,v ,v))))
⇒ twice
54
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(twice 5)
⇒ 10
11. 数値クラス クラス<number>は,<float>及び<integer>という,重なりのない下位クラスをもつ。
11.1 数値クラス
(numberp obj) →真偽値
関数
関数numberpは,objが数値(クラス<number>のインスタンス)である場合はtを返し,それ以外の場
合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (numberp 3)
⇒ t
(numberp -0.3)
⇒ t
(numberp ʼ(a b c))
⇒ nil
(numberp "17")
⇒ nil
(parse-number string) →<number>
関数
関数parse-numberは,string内の文字を(readのように)走査し,結果の字句要素が数値のテキスト表
現である場合は,その数値を返す。
stringが文字列でない場合は,エラーが発生する(エラー名domain-error)。stringが数値のテキスト表現
でない場合は,エラーが発生する(エラー名cannot-parse-number)。
例 (parse-number "123.34")
⇒ 123.34
(parse-number "#XFACE")
⇒ 64206
(parse-number "-37.")
エラーが発生する。
(parse-number "-.5")
エラーが発生する。
これは,浮動小数点数の表記において,小数点の前後の両方
に,少なくとも一つの数字が必要であるためである。
(= x1 x2) →真偽値
関数
関数=は,x1がx2と数学的に等しい値をもつ場合はtを返し,それ以外の場合はnilを返す。x1又はx2の
いずれかが数値でない場合は,エラーが発生する(エラー名domain-error)。
備考 =はeqlとは異なる。=は引数の数学的な値だけ(すなわち,数値としての等価性)を比較する
が,eqlは表現をも比較する。
例 (= 3 4)
⇒ nil
(= 3 3.0)
⇒ t
(= (parse-number "134.54") 134.54)
⇒ t
(= 0.0 -0.0)
⇒ t
(/= x1 x2) →真偽値
関数
関数/=は,x1とx2が数学的に異なる値をもつ場合はtを返し,それ以外の場合はnilを返す。x1又はx2
のいずれかが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (/= 3 4)
⇒ t
(/= 3 3.0)
⇒ nil
55
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(/= (parse-number "134.54") 134.54)
⇒ nil
(>= x1 x2) →真偽値
関数
(<= x1 x2) →真偽値
関数
(> x1 x2) →真偽値
関数
(< x1 x2) →真偽値
関数
関数>=は,x1がx2より大きいか=であるならtを返す。関数<=は,x1がx2より小さいか=であるならtを
返す。関数>は,x1がx2より大きければtを返す。関数<は,x1がx2より小さければtを返す。
これらの関数は,引数の数学的な値を比較する。x1又はx2のいずれかが数値でない場合は,エラーが発
生する(エラー名domain-error)。
例 (> 2 2)
⇒ nil
(> 2.0 2)
⇒ nil
(> 2 -10)
⇒ t
(> 100 3)
⇒ t
(< 2 2)
⇒ nil
(< 1 2)
⇒ t
(>= 2 2)
⇒ t
(>= 2.0 2)
⇒ t
(>= -1 2)
⇒ nil
(<= -1 2)
⇒ t
(<= 2 -1)
⇒ nil
この節の残りの定義において,<float>への型変換は,float又は (convert z <float>) によるものと同じと
する。
(+ x*) →<number>
関数
(* x*) →<number>
関数
関数+及び関数*は,それぞれ引数の和及び積を返す。すべての引数が整数なら結果は整数とする。いず
れかの引数が浮動小数点数なら,結果は浮動小数点数とする。引数がない場合は,+は0を,*は1を返す。
xのいずれかが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (+ 12 3)
⇒ 15
(+ 1 2 3 )
⇒ 6
(+ 12 3.0)
⇒ 15.0
(+ 4 0.0)
⇒ 4.0
(+)
⇒ 0
(* 12 3)
⇒ 36
(* 12 3.0)
⇒ 36.0
(* 4.0 0)
⇒ 0.0
(* 2 3 4)
⇒ 24
(*)
⇒ 1
56
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(- x+) →<number>
関数
関数-は,1個の引数xが与えられると,符号を反転した値を返す。xが数値でない場合は,エラーが発
生する(エラー名domain-error)。
処理系が-0.0と0.0とを区別する場合は, (- 0.0) は-0.0を返す。処理系が-0.0と0.0とを区別しない場合
は, (- 0.0) は0.0を返す。
例 (- 1)
⇒ -1
(- -4.0)
⇒ 4.0
(- 4.0)
⇒ -4.0
(eql (- 0.0) -0.0)
⇒ t
(eql (- -0.0) 0.0)
⇒ t
2個以上の引数x1...xnが与えられた場合は,関数-は,それらの連続した差x1-x2-... -xnを返す。xのいずれ
かが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (- 1 2)
⇒ -1
(- 92 43)
⇒ 49
(- 2.3 -3.0)
⇒ 5.3
(- 0.0 0.0)
⇒ 0.0
(- 3 4 5)
⇒ -6
(reciproca1 x) →<number>
関数
(quotient dividend divisor+) →<number>
関数
関数reciprocalは,引数xの逆数,すなわち,1/xを返す。xがゼロである場合は,エラーが発生する(エ
ラー名 division-by-zero)。
関数quotientは,2個の引数dividend及びdivisorを与えられると,それらの数値の商を返す。結果は,
dividend及びdivisorがいずれも整数で,dividendがdivisorで割り切れるなら,整数とし,そうでなければ
浮動小数点数とする。
3個以上の引数が与えられた場合は,quotientは,dividend / divisor1 / ... / divisornというように,各divisor
に繰り返し作用する。3引数以上のquotientは次のとおり定義できるので,結果の型は2引数の場合に従
う。
(quotient dividend divisor1 divisor2...)
≡(quotient (quotient dividend divisor1) divisor2...)
dividendが数値でない場合は,エラーが発生する(エラー名domain-error)。divisorのいずれかが数値で
ない場合は,エラーが発生する(エラー名domain-error)。いずれかのdivisorがゼロである場合は,エラー
が発生する(エラー名division-by-zero)。
例 (reciproca1 2)
⇒ 0.5
(quotient 10 5)
⇒ 2
(quotient 1 2)
⇒ 0.5
(quotient 2 -0.5)
⇒ -4.0
(quotient 0 0.0)
エラーが発生する。
57
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(quotient 2 3 4)
⇒ 0.16666666666666666
(max x+) →<number>
関数
(min x+) →<number>
関数
関数minは,引数の中で最小の値(負の無限大に最も近い値)を返す。比較は,<によって行う。
関数maxは,引数の中で最大の値(正の無限大に最も近い値)を返す。比較は,>によって行う。
xのいずれかが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (max -5 3)
⇒ 3
(max 2.0 3)
⇒ 3
(max 2 2.0)
⇒ 2又は2.0 (処理系定義)
(max 1 5 2 4 3)
⇒ 5
(min 3 1)
⇒ 1
(min 1 2.0)
⇒ 1
(min 2 2.0)
⇒ 2又は2.0 (処理系定義)
(min 1 5 2 4 3 )
⇒ 1
(abs x) →<number>
関数
関数absは,引数の絶対値を返す。xが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (abs -3)
⇒ 3
(abs 2.0)
⇒ 2.0
(abs -0.0)
⇒ 0.0
(exp x) →<number>
関数
関数expは,eのx乗を返す。ここで,eは,自然対数の底とする。xが数値でない場合は,エラーが発
生する(エラー名domain-error)。
例 (exp 1)
⇒ 2.718281828459045
(exp 2)
⇒ 7.38905609893065
(exp 1.23)
⇒ 3.4212295362896734
(exp 0)
⇒ 1又は1.0(処理系定義)
(log x) →<number>
関数
関数logは,xの自然対数を返す。xが正の数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (log 2.718281828459045)
⇒ 1.0
(log 10)
⇒ 2.302585092994046
(log 1)
⇒ 0又は0.0 (処理系定義)
(expt x1 x2) →<number>
関数
関数exptは,x1のx2乗を返す。x1が整数でx2が非負整数ならば,結果は整数とする。x1がゼロでx2が
負,x1がゼロでx2が浮動小数点数のゼロ,又はx1が負でx2が整数でない場合は,エラーが発生する。
58
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
例 (expt 2 3)
⇒ 8
(expt -100 2)
⇒ 10000
(expt 4 -2)
⇒ 0.0625
(expt 0.5 2)
⇒ 0.25
(expt x 0)
⇒ 1
xが,整数の場合
(expt x 0)
⇒ 1.0 xが,浮動小数点数の場合
(expt -0.25 -1)
⇒ -4.0
(expt 100 0.5)
⇒ 10.0
(expt 100 -1.5)
⇒ 0.001
(expt x 0.0)
⇒ 1.0
xが,正の浮動小数点数の場合
(expt 0.0 0.0)
エラーが発生する。
(sqrt x) →<number>
関数
関数sqrtは,xの正の平方根を返す。xが非負の数値でない場合は,エラーが発生する(エラー名
domain-error)。
例 (sqrt 4)
⇒ 2
(sqrt 2)
⇒ 1.4142135623730951
(sqrt -1) エラーが発生する。
(sin x) →<number>
関数
(cos x) →<number>
関数
(tan x) →<number>
関数
関数sinは,xの正弦を返す。関数cosは,xの余弦を返す。関数tanは,xの正接を返す。どの場合もx
はラジアンで与える。
xが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 ;; これらの結果における浮動小数点数の精度は,
;; 処理系によって異なる可能性があることに注意せよ。
(sin 1)
⇒ 0.8414709848078965
(sin 0)
⇒ 0又は0.0 (処理系定義)
(sin 0.001)
⇒ 9.999998333333417E-4
(cos 1)
⇒ 0.5403023058681398
(cos 0)
⇒ 1又は1.0 (処理系定義)
(cos 0.001)
⇒ 0.9999995000000417
(tan 1)
⇒ 1.557407724654902
(tan 0)
⇒ 0又は0.0 (処理系定義)
(tan 0.001)
⇒ 0.0010000003333334668
(atan x) →<number>
関数
関数atanは,xの逆正接を返す。
59
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
結果は,−π/2を超えπ/2未満の数値とする。
xが数値でない場合は,エラーが発生する(エラー名domain-error)。
(atan2 x1 x2) →<number>
関数
関数atan2は,点の直交座標 (x2, x1) を与えられて,その点の極座標の偏角を返す。x1がゼロでx2が負な
ら結果は正とする。x1及びx2がいずれもゼロならば,結果は処理系定義とする。
yの条件 xの条件 座標位置
結果の値域
y=0
x>0
x軸の正方向 0
* y=+0
x>0
x軸の正方向 +0
* y=−0
x>0
x軸の正方向 −0
y>0
x>0
第1象限
0<結果<π/2
y>0
x=0
y軸の正方向 π/2
y>0
x<0
第2象限
π/2<結果<π
y=0
x<0
x軸の負方向 π
* y=+0
x<0
x軸の負方向 π
* y=−0
x<0
x軸の負方向 −π
y<0
x<0
第3象限
−π<結果<−π/2
y<0
x=0
y軸の負方向 −π/2
y<0
x>0
第4象限
−π/2<結果<0
y=0
x=0
原点
処理系定義
* y=+0
x=+0
原点
+0
* y=−0
x=+0
原点
−0
* y=+0
x=−0
原点
π
* y=−0
x=−0
原点
−π
図3 atan2の象限情報
x1又はx2のいずれかが数値でない場合は,エラーが発生する(エラー名domain-error)。
atan2の値は,負のゼロが実装されていなければ,常に-πを超えπまでの間とする。負のゼロが実装され
ていれば,-πも値域に含むものとする。
x1及びx2の符号が象限情報を得るために用いられる。その詳細を図3に示す。この図では,x1をy,x2
をxと表記する。アステリスク (*) は,負のゼロを実装した処理系に適用されることを意味する。
例 (atan2 0 3.0)
⇒ 0又は0.0(処理系定義)
(atan2 1 1)
⇒ 0.7853981633974483
(atan2 1.0 -0.3)
⇒ 1.8622531212727635
(atan2 0.0 -0.5)
⇒ 3.141592653589793
(atan2 -1 -1)
⇒ -2.356194490192345
(atan2 -1.0 0.3)
⇒ -1.2793396
(atan2 0.0 0.5)
⇒ 0.0
(defun asin (x) (atan2 x (sqrt (-1 (expt x 2)))))
⇒ asin
(defun acos (x) (atan2 (sqrt (-1 (expt x 2))) x))
⇒ acos
(defun atan (x) (atan2 x 1))
⇒ atan
60
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(sinh x) →<number>
関数
(cosh x) →<number>
関数
(tanh x) →<number>
関数
関数sinhは,xの双曲線正弦を返す。関数coshは,xの双曲線余弦を返す。関数tanhは,xの双曲線正
接を返す。
xが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (sinh 1)
⇒ 1.1752011936438014
(sinh 0)
⇒ 0又は0.0 (処理系定義)
(sinh 0.001)
⇒ 0.001000000166666675
(cosh 1)
⇒ 1.5430806348152437
(cosh 0)
⇒ 1又は1.0 (処理系定義)
(cosh 0.001)
⇒ 1.0000005000000416
(tanh 1)
⇒ 0.7615941559557649
(tanh 0)
⇒ 0又は0.0 (処理系定義)
(tanh 0.001)
⇒ 9.999996666668002E-4
(atanh x) →<number>
関数
関数atanhは,xの双曲線逆正接を返す。xが絶対値1未満の数値でない場合は,エラーが発生する(エ
ラー名domain-error)。
例 (atanh 0.5)
⇒ 0.5493061443340549
(atanh 0)
⇒ 0又は0.0 (処理系定義)
(atanh 0.001)
⇒ 0.0010000003333335335
(defun asinh (x) (atanh (quotient x (sqrt (+ 1 (expt x 2)))))) ⇒ asinh
(defun acosh (x) (atanh (quotient (sqrt (* (- x 1) (+ x 1))) x))) ⇒ acosh
11.2 浮動小数点数クラス 浮動小数点数は,<float>クラスのインスタンスとする。浮動小数点数は,あ
る精度の有理数によって表される(IEEE standard 754参照)。
浮動小数点数の書式は,次のいずれかとする。
[s]dd...d.dd...d
[s]dd...d.dd...dE[s]dd...d
[s]dd...d.dd...de[s]dd...d
[s]dd...dE[s] dd...d
[s]dd...de[s] dd...d
ここで,sは “+” 又は “-” のいずれかとし,dd...dは一つ以上の “0” 〜 “9” からなる数字列とする。
*pi*→<float>
名前付き定数
この定数の値は,円周率πの近似値とする。
例 *pi*
⇒ 3.141592653589793
*most-positive-float*→<float>
名前付き定数
61
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
*most-negative-float*→<float>
名前付き定数
*most-positive-float*の値は,正の無限大に最も近い処理系依存の浮動小数点数とする。
*most-negative-float*の値は,負の無限大に最も近い処理系依存の浮動小数点数とする。
(floatp obj) →真偽値
関数
関数floatpは,objが浮動小数点数(クラス<float>のインスタンス)である場合はtを返し,それ以外の
場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (floatp "2.4")
⇒ nil
(floatp 2)
⇒ nil
(floatp 2.0)
⇒ t
(float x) →<float>
関数
関数floatは,xがクラス<float>のインスタンスならばx自身を返し,そうでなければxの浮動小数点近
似値を返す。xが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (float 0)
⇒ 0.0
(float 2)
⇒ 2.0
(float -2.0)
⇒ -2.0
(float 123456789123456789123456789)
⇒ 1.2345678912345679E26
(floor x) →<integer>
関数
関数floorは,x以下の最大の整数を返す。すなわち,xを負の無限大方向に丸める。xが数値でない場
合は,エラーが発生する(エラー名domain-error)。
例 (floor 3.0)
⇒ 3
(floor 3.4)
⇒ 3
(floor 3.9)
⇒ 3
(floor -3.9)
⇒ -4
(floor -3.4)
⇒ -4
(floor -3.0)
⇒ -3
(ceiling x) →<integer>
関数
関数ceilingは,x以上の最小の整数を返す。すなわち,xを正の無限大方向に丸める。xが数値でない場
合は,エラーが発生する(エラー名domain-error)。
例 (ceiling 3.0)
⇒ 3
(ceiling 3.4)
⇒ 4
(ceiling 3.9)
⇒ 4
(ceiling -3.9)
⇒ -3
(ceiling -3.4)
⇒ -3
(ceiling -3.0)
⇒ -3
(truncate x) →<integer>
関数
62
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数truncateは,0〜xの間でxに最も近い整数を返す。すなわち,xをゼロ方向に丸める。xが数値でな
い場合は,エラーが発生する(エラー名domain-error)。
例 (truncate 3.0)
⇒ 3
(truncate 3.4)
⇒ 3
(truncate 3.9)
⇒ 3
(truncate -3.4)
⇒ -3
(truncate -3.9)
⇒ -3
(truncate -3.0)
⇒ -3
(round x) →<integer>
関数
関数roundは,xに最も近い整数を返す。xが二つの整数のちょうど中間にある場合は,偶数が採られる。
xが数値でない場合は,エラーが発生する(エラー名domain-error)。
例 (round 3.0)
⇒ 3
(round 3.4)
⇒ 3
(round -3.4)
⇒ -3
(round 3.6)
⇒ 4
(round -3.6)
⇒ -4
(round 3.5)
⇒ 4
(round -3.5)
⇒ -4
(round 2.5)
⇒ 2
(round -0.5)
⇒ 0
11.3 整数クラス 整数オブジェクトは,数学の整数に対応する。整数は,<integer>クラスのインスタン
スとして表現する。
整数だけを扱う算術演算は,整数の大きさに関係なく数学的に正しく動作する。整数の算術演算がハー
ドウェアの精度を超える結果又は中間結果を生成する場合は,ISLISP処理系は,数学的正しさを確実にす
るために必要な演算を,ソフトウェアで擬似的に処理しなければならない。どのような状況でこの擬似的
処理が必要となるかは,処理系定義とする。この擬似的処理が,いつ処理系の能力を超えるかも処理系定
義とする。
整数の書式は,次のいずれかとする。
#B [s]bb...b
各bは “0” 又は “1”
#b [s]bb...b
各bは “0” 又は “1”
#O [s]oo...o
各oは “0” 〜 “7” のいずれか
#o [s]oo...o
各oは “0” 〜 “7” のいずれか
[s]dd...d
各dは “0” 〜 “9” のいずれか
#X [s]xx...x
各xは “0” 〜 “9”,“A” 〜 “F”,“a” 〜 “f” のいずれか
#x [s]xx...x
各xは “0” 〜 “9”,“A” 〜 “F”,“a” 〜 “f” のいずれか
ここで,sは “+” 又は “-” とする。
備考 ISLISPでは,入力機構を制御する変数はないので,上の表現は厳密に整数の表現となる。
(integerp obj) →真偽値
関数
63
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数integerpは,objが整数(クラス<integer>のインスタンス)である場合はtを返し,それ以外の場合
はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (integerp 3)
⇒ t
(integerp 3.4)
⇒ nil
(integerp "4")
⇒ nil
(integerp ʼ(a b c))
⇒ nil
(div z1 z2) →<integer>
関数
(mod z1 z2) →<integer>
関数
関数divは,z1をz2で割った商以下の最大の整数を返す。z2がゼロである場合は,エラーが発生する(エ
ラー名division-by-zero)。
関数modは,z1のz2による整数除算の余りを返す。結果の符号は,z2の符号と一致する。結果は0とz2
との間(0を含み,z2を含まない。)の整数であり,z1とこの結果との差はz2で割り切れる。
divとmodとの関係は次のとおりとする。
(= z1 (+ (* (div z1 z2) z2) (mod z1 z2)))
すなわち,上の評価形式の評価結果は,常にtとなる。
z1又はz2のいずれかが整数でない場合は,エラーが発生する(エラー名domain-error)。
例 (div 12 3)
⇒4
(div 14 3)
⇒ 4
(div -12 3)
⇒ -4
(div -14 3)
⇒ -5
(div 12 -3)
⇒ -4
(div 14 -3)
⇒ -5
(div -12 -3)
⇒ 4
(div -14 -3)
⇒ 4
(mod 12 3)
⇒ 0
(mod 7 247)
⇒ 7
(mod 247 7)
⇒ 2
(mod 14 3)
⇒ 2
(mod -12 3)
⇒ 0
(mod -14 3)
⇒ 1
(mod 12 -3)
⇒ 0
(mod 14 -3)
⇒ -1
(mod -12 -3)
⇒ 0
(mod -14 -3)
⇒ -2
(gcd z1 z2) →<integer>
関数
関数gcdは,二つの引数の最大公約数を返す。結果は,非負整数とする。ゼロ以外の引数に対しては,
最大公約数は,z1及びz2の両方の約数である最大の整数とする。
64
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
z1又はz2のいずれかが整数でない場合は,エラーが発生する(エラー名domain-error)。
例 (gcd 12 5)
⇒ 1
(gcd 15 24)
⇒ 3
(gcd -15 24)
⇒ 3
(gcd 15 -24)
⇒ 3
(gcd -15 -24)
⇒ 3
(gcd 0 -4)
⇒ 4
(gcd 0 0)
⇒ 0
(lcm z1 z2) →<integer>
関数
関数lcmは,その引数の最小公倍数を返す。gcd及びlcmは,次の関係を満たす。
(= (* (gcd m n) (lcm m n)) (abs (* m n)))
すなわち,上の評価形式の評価結果は,常にtとなる。
z1又はz2のいずれかが整数でない場合は,エラーが発生する(エラー名domain-error)。
例 (lcm 2 3)
⇒ 6
(lcm 15 24)
⇒ 120
(lcm 15 -24)
⇒ 120
(lcm -15 24)
⇒ 120
(lcm -15 -24)
⇒ 120
(lcm 0 -4)
⇒ 0
(lcm 0 0)
⇒ 0
(isqrt z) →<integer>
関数
関数isqrtは,zの正の平方根以下の最大の整数を返す。zが非負整数でない場合は,エラーが発生する
(エラー名domain-error)。
例 (isqrt 49)
⇒ 7
(isqrt 63)
⇒ 7
(isqrt 1000000000000002000000000000000) ⇒ 1000000000000000
12. 文字クラス 文字は,<character>クラスのインスタンスとして表現する。これによって,利用者は特
定の文字コードに依存しなくてもよくなる。
ISLISPの文字集合は,少なくとも95個の印字文字と復帰改行文字とを含まなければならない。印字文
字は,スペース文字及び次の94個の文字からなる。
! " # $ % & ʼ ( ) * + , - ./ 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ ̲
ʻ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } 〜
文字リテラルは,#\とそれに続く文字自身,又は文字が名前をもつ場合は#\とそれに続く名前によっ
て表記する。例えば,英文字のAは,“#\A”と表記する。復帰改行文字及びスペース文字は,それぞれ
“newline”及び“space”という名前をもつので,それらは“#\newline”及び“#\space”と表記するこ
65
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
とができる。(文字の名前では,大文字小文字は区別しない。)
すべての文字は,char<によって順序付けられるが,その順序は,次の順序を満たすものとする。
A<B<C<D<E<F<G<H<I<J<K<L<M<N<O<P<Q<R<S<T<U<V<W<X<Y<Z
a<b<c<d<e<f<g<h<i<j<k<l<m<n<o<p<q<r<s<t<u<v<w<x<y<z
0<1<2<3<4<5<6<7<8<9
ここで,char1<char2は, (char< char1 char2) が真であることを意味する。
(characterp obj) →真偽値
関数
関数characterpは,objが文字(クラス<character>のインスタンス)である場合はtを返し,それ以外の
場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (characterp #\a)
⇒ t
(characterp "a")
⇒ nil
(characterp ʼa)
⇒ nil
(char= char1 char2) →真偽値
関数
(char/= char1 char2) →真偽値
関数
(char< char1 char2) →真偽値
関数
(char> char1 char2) →真偽値
関数
(char<= char1 char2) →真偽値
関数
(char>= char1 char2) →真偽値
関数
関数char=は,char1がchar2と同じ文字かどうか検査する。関数char<は,char1がchar2より小さいかど
うか検査する。関数char<=は,char1がchar2以下かどうか検査する。ここで使用される順序は,上で定義
した部分的な順序関係に従い,処理系定義の方式ですべての文字に対する全順序に拡張したものとする。
検査する条件が満たされればtを返し,そうでなければnilを返す。
二つの文字は,それらがchar=でない場合に,char/=とする。二つの文字は,それらがchar<=でない場合
に,char>とする。二つの文字は,それらがchar<でない場合に,char>=とする。
char1又はchar2のいずれかが文字でない場合は,エラーが発生する(エラー名domain-error)。
例 (char= #\a #\a)
⇒ t
(char= #\a #\b)
⇒ nil
(char= #\a #\A)
⇒ nil
(char/= #\a #\a)
⇒ nil
(char< #\a #\a)
⇒ nil
(char< #\a #\b)
⇒ t
(char< #\b #\a)
⇒ nil
(char< #\a #\A)
⇒ nil又はt(処理系定義)
(char< #\* #\a)
⇒ nil又はt(処理系定義)
(char> #\b #\a)
⇒ t
(char<= #\a #\a)
⇒ t
(char<= #\a #\A)
⇒ nil又はt(処理系定義)
(char>= #\b #\a)
⇒ t
66
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(char>= #\a #\a)
⇒ t
13. リストクラス クラス<list>は,二つの下位クラス<cons>及び<null>に分割される。
13.1 コンス コンス(“ドット対”とも呼ばれる。)は,二つの構成要素をもつ。左側の構成要素をcar
と呼び,右側の構成要素をcdrと呼ぶ。このクラスの生成関数は,consとする。コンスは,次のとおり表
記する。
(car .cdr)
ここで,car及びcdrは,それぞれコンスオブジェクトのcar要素及びcdr要素の値を表す。特別な場合
として,cdrの値がnilであるとき,コンスオブジェクトは,次のとおり表記する。
(car)
一般に,コンスオブジェクトから構成されるデータ構造は,次のいずれかの書式で表記する。
(x1 .(x2 .... (xn-1 .xn) ...))
(x1 .(x2 .... (xn-1) ...))
これらはそれぞれ,次のとおり表記できる。
(x1 x2...xn-1 .xn)
(x1 x2...xn-1)
(consp obj) →真偽値
関数
関数conspは,objがコンス(クラス<cons>のインスタンス)である場合はtを返し,それ以外の場合は
nilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (consp ʼ(a . b))
⇒ t
(consp ʼ(a b c))
⇒ t
(consp ʼ())
⇒ nil
(consp #(a b))
⇒ nil
(cons obj1 obj2) →<cons>
関数
関数consは,二つのオブジェクトからコンスを作成して返す。obj1をそのcar要素とし,obj2をcdr要素
とする。要求されたコンスが割り当てられない場合は,エラーが発生する(エラー名cannot-create-cons)。
obj1及びobj2は,いかなるISLISPオブジェクトでもよい。
例 (cons ʼa ʼ())
⇒ (a)
(cons ʼ(a) ʼ(b c d))
⇒ ((a) b c d)
(cons "a" ʼ(b c))
⇒ ("a" b c)
(cons ʼa 3)
⇒ (a . 3)
(cons ʼ(a b) ʼ(c)
⇒ ((a b) . c)
(car cons) →<object>
関数
関数carはconsのcar要素を返す。consがコンスでない場合は,エラーが発生する(エラー名domain-error)。
例 (car ʼ())
エラーが発生する。
(car ʼ(a b c))
⇒ a
(car ʼ((a) b c d))
⇒ (a)
67
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(car ʼ(1 . 2))
⇒ 1
(cdr cons) →<object>
関数
関数cdrはconsのcdr要素を返す。consがコンスでない場合は,エラーが発生する(エラー名domain-error)。
例 (cdr ʼ())
エラーが発生する。
(cdr ʼ((a) b c d))
⇒ (b c d)
(cdr ʼ(1 . 2))
⇒ 2
(setf (car cons) obj) →<object>
特殊形式
(set-car obj cons) →<object>
関数
これらは,carで示される場所指定を受け取り,<cons>クラスのインスタンスのcar要素をobjで更新す
る。返り値はobjとする。consがコンスでない場合は,エラーが発生する(エラー名domain-error)。obj
は,いかなるISLISPオブジェクトでもよい。
例 (let((x (list ʼapple ʼorange)))
(list x (carx)
(setf (car x) ʼbanana)
x (car x)))
⇒ ((banana orange) apple banana (banana orange) banana)
(setf (cdr cons) obj) →<object>
特殊形式
(set-cdr obj cons) →<object>
関数
これらは,cdrで示される場所指定を受け取り,<cons>クラスのインスタンスのcdr要素をobjで更新す
る。返り値は,objとする。consがコンスでない場合は,エラーが発生する(エラー名domain-error)。obj
は,いかなるISLISPオブジェクトでもよい。
例 (let ((x (list ʼapple ʼorange)))
(list x (cdr x)
(setf (cdr x) ʼbanana)
x (cdr x)))
⇒ ((apple . banana) (orange) banana (apple . banana) banana)
13.2 空リストクラス このクラスは,nilと呼ばれるただ一つの要素からなる。このオブジェクトは,真
偽値式における偽の値とする。列nilの長さは,0とする。
(null obj) →真偽値
関数
関数nullは,objがnilである場合はtを返し,それ以外の場合はnilを返す(5)。objは,いかなるISLISP
オブジェクトでもよい。
注(5) 命名の方式を厳格に守るならば,nullは,nullpと名付けられなければならない。しかし,歴史
的及び互換性の理由で,nullと名付ける。
例 (null ʼ(abc))
⇒ nil
(null ʼ())
⇒ t
(null (list))
⇒ t
68
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
13.3 リスト操作
(listp obj) →真偽値
関数
関数listpは,objがリスト(クラス<list>のインスタンス)である場合はtを返し,それ以外の場合はnil
を返す。objは,いかなるISLISPオブジェクトでもよい。
例 (listp ʼ(a b c))
⇒ t
(listp ʼ())
⇒ t
(listp ʼ(a . b))
⇒ t
(let ((x (list ʼa)))
(setf (cdr x) x)
(listp x))
⇒ t
(listp "abc")
⇒ nil
(listp #(1 2))
⇒ nil
(listp ʼtakayasu)
⇒ nil
(create-list i [initial-element]) →<list>
関数
関数create-listは,長さiのリストを生成して返す。initial-elementが与えられた場合,新しいリストの要
素を,このオブジェクトで初期化する。そうでなければ,初期化は処理系定義とする。要求されたリスト
の割当てができない場合は,エラーが発生する(エラー名cannot-create-list)。iが非負整数でない場合は,
エラーが発生する(エラー名domain-error)。initial-elementは,いかなるISLISPオブジェクトでもよい。
例 (create-list 3 17)
⇒ (17 17 17)
(create-list 2 #\a)
⇒ (#\a #\a)
(list obj*) →<list>
関数
関数listは,その長さが引数の個数と一致し,すべての引数を同じ順序で要素とする新しいリストを返
す。要求されたリストの割当てができない場合は,エラーが発生する(エラー名cannot-create-list)。各obj
は,いかなるISLISPオブジェクトでもよい。
例 (list ʼa(+ 3 4) ʼc)
⇒ (a 7 c)
(list)
⇒ nil
(reverse list) →<list>
関数
(nreverse list) →<list>
関数
これらの関数は,どちらも与えられたlistの要素の順序が逆転したリストを返す。listがリストでない場
合は,エラーが発生する(エラー名domain-error)。
reverseでは,与えられたlistに対する副作用はない。結果となるリストは,与えられたlistと構造を共
有してもよい。
nreverseでは,新しいリストを作る目的で,与えられたlistの最上位を構成するコンスに対して副作用を
及ぼしてもよい。リテラルオブジェクトに対しては,nreverseを適用してはならない。
例 (reverse ʼ(a b c d e))
⇒ (e d c b a)
(reverse ʼ(a))
⇒ (a)
69
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(reverse ʼ())
⇒ ()
(let* ((x (list ʼa ʼb)) (y (nreverse x))) (equal x y))
⇒ 処理系定義
(append list*) →<list>
関数
関数appendは,すべてのlistを連結した結果を返す。listが与えられなかった場合は,()を返す。list
のいずれかがリストでない場合は,エラーが発生する(エラー名domain-error)。
この関数は,その引数を変更しない。結果と引数listとが構造を共有するかどうか,更に,どのような
場合に共有するかは,処理系定義とする。
リストの割当てができない場合は,エラーが発生する(エラー名cannot-create-list)。
例 (append ʼ(a b c) ʼ(d e f))
⇒ (a b c d e f)
(member obj list) →<list>
関数
関数memberは,listの中にobjとeqlであるオブジェクトが含まれている場合,そのcarがobjとeqlで
あるlistの最初の部分リストを返す。そうでなければnilを返す。listがリストでない場合は,エラーが発
生する(エラー名domain-error)。
例 (member ʼc ʼ(a b c d e f))
⇒ (c d e f)
(member ʼg ʼ(a b c d e f))
⇒ nil
(member ʼc ʼ(a b c a b c))
⇒ (c a b c)
(mapcar function list+) →<list>
関数
(mapc function list+) →<list>
関数
(maplist function list+) →<list>
関数
(mapl function list+) →<list>
関数
(mapcan function list+) →<list>
関数
(mapcon function list+) →<list>
関数
これらの関数は,与えられた一連のlistによって決定される引数の集合に,与えられたfunctionを連続し
て適用する。引数を決定する方法及び結果を蓄積していく方法が,関数によって異なる。
関数
引数
結果
mapcar
要素
返り値のリスト
mapc
要素
最初のlist
maplist
部分リスト
返り値のリスト
mapl
部分リスト
最初のlist
mapcan
要素
返り値を破壊的に連結した結果
mapcon
部分リスト
返り値を破壊的に連結した結果
mapcarは,各listの要素に対して順に演算を行う。functionは,各listの第1要素に対して適用され,次
に各listの第2要素に対して適用され,これを順次繰り返す。最も短いlistが終わったときに,繰返しは終
了し,他のリストの余った要素は無視される。mapcarが返す値は,functionの呼出し順にそれらの結果を
リストにしたものとする。
mapcは,mapcarと似ているが,functionの適用結果を蓄積しない点が異なる。関数mapcは,最初のlist
を返す。
maplistは,mapcarと似ているが,functionを各listの部分リストに適用する点が異なる。functionは,各
70
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
list自身に最初に適用され,次に各listのcdrに適用され,次に各listのcdrのcdrに適用され,これを順次
繰り返す。
maplは,maplistと似ているが,functionの適用結果を蓄積しない点が異なる。関数maplは,最初のlist
を返す。
mapcan及びmapconは,それぞれmapcar及びmaplistに似ているが,functionの適用結果を一つのリスト
に結合する際に,listではなくappendと同様の操作を破壊的に実行する演算を用いる点が異なる。
functionが関数でない場合は,エラーが発生する(エラー名domain-error)。listのいずれかがリストでな
い場合は,エラーが発生する(エラー名domain-error)。
いずれの関数においても,functionの呼出しは左から右へと進む。したがって,functionが副作用をもつ
場合,利用者はこの順序に依存してよい。
例 (mapcar #ʼcar ʼ((1 a) (2 b) (3 c)))
⇒ (1 2 3)
(mapcar #ʼabs ʼ((3 -4 2 -5 -6))
⇒ (3 4 2 5 6)
(mapcar #ʼcons ʼ(a b c) ʼ(1 2 3))
⇒ ((a . 1) (b . 2) (c . 3))
(let ((x 0)) (mapc (lambda (v) (setq x (+ x v))) ʼ(3 5)) x)
⇒ 8
(maplist #ʼappend ʼ(1 2 3 4) ʼ(1 2) ʼ(1 2 3))
⇒ ((1 2 3 4 1 2 1 2 3) (2 3 4 2 2 3))
(maplist (lambda (x) (cons ʼfoo x)) ʼ(a b c d))
⇒ ((foo a b c d) (foo b c d) (foo c d) (foo d))
(maplist (lambda (x) (if (member (car x) (cdr x)) 0 1))
ʼ(a b a c d b c))
⇒ (0 0 1 0 1 1 1)
(let ((k 0))
(mapl(lambda (x)
(setq k (+ k (if (member (car x) (cdr x)) 0 1))))
ʼ(a b a c d b c))
k)
⇒ 4
(mapcan (lambda (x) (if (> x 0) (list x))) ʼ(-3 4 0 5 -2 7))
⇒ (4 5 7)
(mapcon (lambda (x) (if (member (car x) (cdr x)) (list (car x))))
ʼ(a b a c d b c b c))
⇒ (a b c b c)
(mapcon #ʼlist ʼ(1 2 3 4))
⇒ ((1 2 3 4) (2 3 4) (3 4) (4))
71
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(assoc obj association-list) →<list>
関数
関数assocは,association-listの中に,そのcarがobjとeqlであるコンスが少なくとも一つ含まれている
場合,そのような最初のコンスを返す。そうでなければnilを返す。association-listがコンスのリストでな
い場合は,エラーが発生する(エラー名domain-error)。
例 (assoc ʼa ʼ((a . 1) (b . 2)))
⇒ (a . 1)
(assoc ʼa ʼ((a . 1) (a . 2)))
⇒ (a . 1)
(assoc ʼc ʼ((a . 1) (b . 2)))
⇒ nil
14. 配列
14.1 配列のクラス 配列は,その構成要素にデータを格納する。配列の構成要素は,添字 (index) と呼
ばれる非負整数の組を使ってアクセスできる。
配列中の要素の総数は,各次元の大きさの積とする。0次元の配列も許され,この規則の結果として,
ちょうど一つの要素を格納する事ができ,添字なしにアクセスされる。
配列のクラスは複数存在する。それらの継承関係を,図1に示す。各クラスの用途を,次に示す。
・ <basic-array>
すべての配列は抽象クラス<basic-array>に属するが,(すべての抽象クラスがそうであるように)こ
のクラスは直接インスタンスをもたない。このクラスは,型の識別のためだけに用意されている。
<basic-array>は,下位クラス<basic-vector>及び<basic-array*>をもつ。これらのクラスは,重なりが
なく,配列の集合を完全に分割する。これ以外には<basic-array>の直接の下位クラスは,存在しない。
・ <basic-vector>
すべての1次元の配列は抽象クラス<basic-vector>に属するが,(すべての抽象クラスがそうである
ように)このクラスは直接インスタンスをもたない。このクラスは,型の識別のためだけに用意され
ている。
<basic-vector>は,下位クラス<general-vector>及び<string>をもつ。<basic-vector>は,付加的な処理系
定義の下位クラスをもってもよい。
備考 処理系が,ビットの1次元配列のために,特殊化された配列表現を用意する場合がある。その
場合,そのような配列表現は,<basic-vector>の下位クラスになるであろう。
・ <general-vector>
クラス<general-vector>のオブジェクトは,<object>型の要素を格納可能な1次元の配列とする。関数
create-arrayが1次元配列を作成するよう命令された場合,結果の配列は,このクラスに属する。
・ <string>
クラス<string>のオブジェクトは,<character>型の要素だけを格納可能な1次元の配列とする。関数
create-stringが用いられた場合,結果は,このクラスに属する。
・ <basic-array*>
1次元でないすべての配列は抽象クラス<basic-array*>に属するが,(すべての抽象クラスがそうで
あるように)このクラスは直接インスタンスをもたない。このクラスは,型の識別のためだけに用意
されている。
ISLISPは,<basic-array*>に直接の下位クラスを一つだけ定義する。その下位クラスを,
<general-array*>とする。<basic-array*>には,処理系定義の付加的な下位クラスが存在してもよい。
72
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
備考 処理系が,モノクローム又はカラーのスクリーンの表示情報を保持する目的で,1ビット以上
の2次元配列のために,特殊化された配列表現を用意する場合がある。その場合,そのような
配列表現は,<basic-array*>の下位クラスになるであろう。
・ <general-array*>
クラス<general-array*>のオブジェクトは,<object>型の要素を格納可能な1次元でない配列とする。
関数create-arrayが1次元でない配列を作成するよう命令された場合,結果の配列は,このクラスに属
する。
14.2 一般配列 クラス<general-vector>又はクラス<general-array*>に属するオブジェクトは,一般配列
(general array) と呼ばれることがある。
一般配列は,クラス<object>のいかなるオブジェクトも格納可能とする。一般配列以外の配列は,より
特殊化されたクラスのオブジェクトを格納するための制限された配列とする。
一般配列は,その配列の内容を示す並びを入れ子となったリストにして続ける#ra記法(rは配列の次元
数を表す整数)を用いて,リテラルとして表現可能とする。その構造は,次のように定義できる。r=1の
とき,配列構造は単純に (obj1...objn) とする。r>1のとき,各次元の大きさをn1,n2,...,nrとすると,配列
構造は (str1...strn1) となる。ここで,striはr−1次元の部分配列構造であり,個々の部分配列の各次元の大
きさはn2,...,nrとする。例えば,(create-array ʼ( 2 3 4) 5)が生成する配列は,次のように表記する。
#3a (((5 5 5 5) (5 5 5 5) (5 5 5 5)) ((5 5 5 5) (5 5 5 5) (5 5 5 5)))
14.3 配列操作 配列操作のためにISLISPは,次の関数を用意する。
(basic-array-p obj) →真偽値
関数
(basic-array*-p obj) →真偽値
関数
(general-array*-p obj) →真偽値
関数
関数basic-array-pは,objが配列(クラス<basic-array>のインスタンス)である場合はtを返し,それ以
外の場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
関数basic-array*-pは,objがクラス<basic-array*>のインスタンスである場合はtを返し,それ以外の場
合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
関数general-array*-pは,objがクラス<general-array*>のインスタンスである場合はtを返し,それ以外の
場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (mapcar (lambda (x)
(list (basic-array-p x)
(basic-array*-p x)
(general-array*-p x)))
ʼ((a b c)
"abc"
#(a b c)
#1a(a b c)
#2a((a) (b) (c))))
⇒ ((nil nil nil) (t nil nil) (t nil nil) (t nil nil) (t t t))
(create-array dimensions [initial-element]) →<basic-array>
関数
73
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数create-arrayは,新しい配列を生成し,その配列を値として返す。dimensions引数は,非負整数のリ
ストとする。生成される配列の次元数はdimensionsの長さと一致し,各次元の大きさは,dimensionsの各
要素の値と一致する。
結果は,一次元ならばクラス<general-vector>に属し,そうでなければ<general-array*>に属する。
initial-elementが与えられれば,新しい配列の要素は,このオブジェクトで初期化され,そうでなければ
初期化は処理系定義とする。
要求された配列の割当てができない場合は,エラーが発生する(エラー名cannot-create-array)。
dimensionsが非負整数のリストでない場合は,エラーが発生する(エラー名domain-error)。
initial-elementは,いかなるISLISPオブジェクトでもよい。
例 (create-array ʼ(2 3) 0.0)
⇒ #2a((0.0 0.0 0.0) (0.0 0.0 0.0))
(create-array ʼ(2) 0.0)
⇒ #(0.0 0.0)
(aref basic-array z*) →<object>
関数
(garef general-array z*) →<object>
関数
関数arefは,整数zの並びで特定されるbasic-arrayの構成要素に格納されたオブジェクトを返す。この
並びは,basic-arrayの次元数と正確に同じ個数の要素をもたなければならず,その各々は,0≤zI<diを満た
さなければならない。ここで,diは第i次元の大きさで,次元数をdとするとき,0≤i<dとする。配列の
添字は,0から始まる。したがって,i番目の行は添字i−1でアクセスする。
basic-arrayが配列でない場合は,エラーが発生する(エラー名domain-error)。zのいずれかが非負整数
でない場合は,エラーが発生する(エラー名domain-error)。
関数garefは,arefと似ているが,第1引数general-arrayが,クラス<general-vector>又はクラス
<general-array*>のインスタンスでない場合は,エラーが発生する(エラー名domain-error)。
例 (defglobal array1 (create-array ʼ(3 3 3) 0)) ⇒ array1
array1
⇒ #3a(((0 0 0) (0 0 0) (0 0 0))
((0 0 0) (0 0 0) (0 0 0))
((0 0 0) (0 0 0) (0 0 0)))
(aref array1 0 1 2)
⇒ 0
(setf (aref array1 0 1 2) 3.14)
⇒ 3.14
(aref array1 0 1 2)
⇒ 3.14
(aref (create-array ʼ(8 8) 6) 1 1)
⇒ 6
(aref (create-array ʼ() 19))
⇒ 19
(setf (aref basic-array z*) obj) →<object>
特殊形式
(set-aref obj basic-array z*) →<object>
関数
(setf (garef general-array z*) obj) →<object>
特殊形式
(set-garef obj general-array z*) →<object>
関数
これらは,aref又はgarefによって取得可能なオブジェクトをobjで置き換える。返り値は,objとする。
74
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
basic-array,general-array及び添字zの並びに関する制約条件は,aref及びgarefのものと同じとする。
例 (setf (aref array1 0 1 2) 3.15)
⇒ 3.15
(set-aref 51.3 array1 0 1 2)
⇒ 51.3
(array-dimensions basic-array) →<list>
関数
関数array-dimensionsは,与えられたbasic-arrayの各次元の大きさをリストとして返す。basic-arrayが
クラス<basic-array>のインスタンスでない場合は,エラーが発生する(エラー名domain-error)。返り値の
リストが変更された場合は,結果は未定義とする。
例 (array-dimensions
(create-array ʼ(2 2) 0))
⇒ (2 2)
(array-dimensions (vector ʼa ʼb))
⇒ (2)
(array-dimensions "foo")
⇒ (3)
15. ベクタ ベクタは,1次元の配列とする。配列とベクタとの関係については,14.1による。
一般ベクタ(クラス<general-vector>のインスタンス)は,次のとおり表記する。
#(x1 x2...xn)
(basic-vector-p obj) →真偽値
関数
(general-vector-p obj) →真偽値
関数
関数basic-vector-pは,objがクラス<basic-vector>のインスタンスである場合はtを返し,それ以外の場
合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
関数general-vector-pは,objが一般ベクタ(クラス<general-vector>のインスタンス)である場合はtを返
し,それ以外の場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (mapcar (lambda (x)
(list (basic-vector-p x)
(general-vector-p x)))
ʼ((a b c)
"abc"
#(a b c)
#1a(a b c)
#2a((a)(b)(c))))
⇒ ((nil nil) (t nil) (t t) (t t) (nil nil))
(create-vector i [initial-element]) →<general-vector>
関数
関数create-vectorは,長さiの一般ベクタを生成して返す。initial-elementが与えられれば,新しいベク
タの要素は,このオブジェクトで初期化され,そうでなければ,初期化は処理系定義とする。要求された
ベクタの割当てができない場合は,エラーが発生する(エラー名cannot-create-vector)。iが非負整数でな
い場合は,エラーが発生する(エラー名domain-error)。initial-elementは,いかなるISLISPオブジェクト
でもよい。
例 (create-vector 3 17)
⇒ # (17 17 17)
75
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(create-vector 2 #\a)
⇒ # (#\a #\a)
(vector obj*) →<general-vector>
関数
関数vectorは,引数objを要素とする新しい一般ベクタを返す。したがって,新たに作成されるベクタ
の長さは,引数として渡されたobjの個数と一致する。ベクタは,0から長さ未満までの範囲の整数で添
字付けされる。要求されたベクタの割当てができない場合は,エラーが発生する(エラー名
cannot-create-vector)。各objは,いかなるISLISPオブジェクトでもよい。
例 (vector ʼa ʼb ʼc)
⇒ #(a b c)
(vector)
⇒ #()
16. 文字列クラス 文字列は,<character>型の要素だけを格納可能なベクタとする。配列,ベクタ及び文
字列の関係は,14.1による。
処理系定義のいかなる文字も,文字列の要素とすることができる。ISLISPでは,文字列の添字は,0か
ら始まる。要素となるすべての文字を順に並べ,二重引用符“"”で囲むことで,文字列は表記する。文字
列中に二重引用符がある場合,その二重引用符の直前に逆斜線“\”を置かねばならない。文字列中に逆
斜線がある場合,その逆斜線の直前にもう一つの逆斜線“\”を置かねばならない。プログラムテキスト
中にリテラルとして含まれる文字列は,変更不可能なオブジェクトとする。印字文字(12.参照)以外の文
字の表現は,処理系定義とする。
(stringp obj) →真偽値
関数
関数stringpは,objが文字列(クラス<string>のインスタンス)である場合はtを返し,それ以外の場合
はnilを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (stringp "abc")
⇒ t
(stringp ʼabc)
⇒ nil
(create-string i [initial-character]) →<string>
関数
関数create-stringは,長さiの文字列を生成して返す。initial-characterが与えられれば,新しい文字列中
の文字は,この文字initial-characterで初期化され,そうでなければ,初期化は処理系定義とする。要求さ
れた文字列の割当てができない場合は,エラーが発生する(エラー名cannot-create-string)。iが非負整数で
ない場合又はinitial-characterが文字でない場合は,エラーが発生する(エラー名domain-error)。
例 (create-string 3 #\a)
⇒ "aaa"
(create-string 0 #\a)
⇒ ""
(string= string1 string2) →準真偽値
関数
(string/= string1 string2) →準真偽値
関数
(string< string1 string2) →準真偽値
関数
(string> string1 string2) →準真偽値
関数
(string>= string1 string2) →準真偽値
関数
(string<= string1 string2) →準真偽値
関数
関数string=は,string1がstring2と同じ文字列かどうか検査する。関数string<は,string1がstring2より小
76
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
さいかどうか検査する。関数string<=は,string1がstring2以下かどうか検査する。
ここで使用される順序は,文字の比較順序に基づく。
二つの文字列は,それらの長さが同じくlであり,かつ,0<I<lであるすべてのiについて, (char= (elt
string1 i) (elt string2 i))が成り立つ場合に,string=とする。
二つの文字列string1及びstring2は,それぞれの文字が最初に異なる位置において,string1の文字がstring2
の対応する文字と比べてchar<であるか,又は,string1がstring2より長さが短く,かつ,string1中のすべて
の文字がstring2の先頭から一致する場合に,string<とする。
二つの文字列は,それらがstring<であるか又はstring=であれば,string<=とする。
二つの文字列は,それらがstring=でない場合,string/=とする。二つの文字列は,それらがstring<=でな
い場合,string>とする。二つの文字列は,それらがstring<でない場合,string>=とする。
これらの六つの文字列比較関数は,検査する条件が満たされる場合には,処理系定義のnil以外の値を
返し,そうでなければnilを返す。
string1又はstring2のいずれかが文字列でない場合は,エラーが発生する(エラー名domain-error)。
例 (if (string= "abcd" "abcd") t nil)
⇒ t
(if (string= "abcd" "wxyz") t nil)
⇒ nil
(if (string= "abcd" "abcde") t nil)
⇒ nil
(if (string= "abcde" "abcd") t nil)
⇒ nil
(if (string/= "abcd" "wxyz") t nil)
⇒ t
(if (string< "abcd" "abcd") t nil)
⇒ nil
(if (string< "abcd" "wxyz") t nil)
⇒ t
(if (string< "abcd" "abcde") t nil)
⇒ t
(if (string< "abcde" "abcd") t nil)
⇒ nil
(if (string<= "abcd" "abcd") t nil)
⇒ t
(if (string<= "abcd" "wxyz") t nil)
⇒ t
(if (string<= "abcd" "abcde") t nil) ⇒ t
(if (string<= "abcde" "abcd") t nil) ⇒ nil
(if (string> "abcd" "wxyz") t nil)
⇒ nil
(if (string>= "abcd" "abcd") t nil)
⇒ t
(char-index char string [start-position]) →<object>
関数
関数char-indexは,string中のcharの位置を返す。探索は,start-position(文字列の先頭位置を0とする。)
で示される位置から始まる。start-positionの省略時値は0とする。探索に成功した場合に返す値は,string
の先頭からのオフセットであり,探索の開始点からのオフセットではない。charがstring中に存在しなか
った場合は,nilを返す。比較には,関数char=を用いる。
charが文字でない場合又はstringが文字列でない場合は,エラーが発生する(エラー名domain-error)。
例 (char-index #\b "abcab")
⇒ 1
(char-index #\B "abcab")
⇒ nil
(char-index #\b "abcab" 2)
⇒ 4
(char-index #\d "abcab")
⇒ nil
77
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(char-index #\a "abcab" 4)
⇒ nil
(string-index substring string [start-position]) →<object>
関数
関数string-indexは,string中のsubstringの位置を返す。探索は,start-position(文字列の先頭位置を0
とする。)で示される位置から始まる。start-positionの省略時値は0とする。探索に成功した場合に返す値
は,stringの先頭からのオフセットであり,探索の開始点からのオフセットではない。そのsubstringがstring
中に存在しなかった場合は,nilを返す。部分文字列の存在検査は,二つの文字列の対応する要素について,
char=を順次使用することによって実行される。
substring又はstringのいずれかが文字列でない場合は,エラーが発生する(エラー名domain-error)。
例 (string-index "foo" "foobar")
⇒ 0
(string-index " bar " " foobar")
⇒ 3
(string-index " FOO " " foobar")
⇒ nil
(string-index " foo " " foobar" 1)
⇒ nil
(string-index " bar " " foobar" 1)
⇒ 3
(string-index " foo" "")
⇒ nil
(string-index "" "foo”)
⇒ 0
(string-append string*) →<string>
関数
関数string-appendは,各stringの文字の並びを連結して得られる文字列を返す。stringが一つも与えられ
なかった場合は,""を返す。stringのいずれかが文字列でない場合は,エラーが発生する(エラー名
domain-error)。
この関数は,引数を変更しない。結果が引数stringと構造を共有するかどうか,更にどの場合に共有す
るかは,処理系定義とする。
文字列の割当てができない場合は,エラーが発生する(エラー名cannot-create-string)。
例 (string append "abc" "def")
⇒ "abcdef"
(string-append "abc" "abc")
⇒ "abcabc"
(string-append "abc" "")
⇒ "abc"
(string-append "" "abc")
⇒ "abc"
(string-append "abc" "" "def")
⇒ "abcdef"
17. 列 クラス<basic-vector>又はクラス<list>に属するオブジェクトを総称して,列 (sequence) と呼ぶ。
(length sequence) →<integer>
関数
関数lengthは,sequenceの長さを0以上の整数として返す。
sequenceがベクタであれば,lengthは,その長さを返す。
sequenceがリストであれば,結果は,リスト中の要素数とする。要素自身がリストである場合,この部
分リスト中の要素は,数えない。ドットリストの場合,lengthは,リストの最上位のコンスの個数を返す。
例えば,ʼ(a b. c) ≡ (cons ʼa (cons ʼb ʼc)) であることから, (length ʼ(a b . c)) ⇒ 2とする。
sequenceがベクタ又はリストでない場合は,エラーが発生する(エラー名domain-error)。
例 (length ʼ(a b c))
⇒ 3
78
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(length ʼ(a (b) (c d e)))
⇒ 3
(length ʼ())
⇒ 0
(length (vector ʼa ʼb ʼc))
⇒ 3
(elt sequence z) →<object>
関数
列sequence及び0<z< (length sequence) を満たす整数zを与えられると,関数eltは,添字zで示される
sequenceの要素を返す。添字は,0から始まる。すなわち,z=0は,第1要素を指示する。zが,上の範囲
外の整数である場合は,エラーが発生する(エラー名index-out-of-range)。
sequenceがベクタ若しくはリストでない場合又はzが整数でない場合は,エラーが発生する(エラー名
domain-error)。
例 (elt ʼ(a b c) 2)
⇒ c
(elt (vector ʼa ʼb ʼc) 1)
⇒ b
(elt "abc" 0)
⇒ #\a
(setf (elt sequence z) obj) →<object>
特殊形式
(set-elt obj sequence z) →<object>
関数
これらは,eltで示される場所指定を受け取り,この場所をobjで更新する。返り値は,objとする。整
数zは,0<z< (length sequence) を満足しなければならない。
zが正しい添字の範囲外の整数である場合は,エラーが発生する(エラー名index-out-of-range)。sequence
がベクタ若しくはリストでない場合又はzが整数でない場合は,エラーが発生する(エラー名domain-error)。
objは,いかなるISLISPオブジェクトでもよい。
例 (let ((string (create-string 5 #\x)))
(setf (elt string 2) #\0)
x)
⇒ "xx0xx"
(subseq sequence z1 z2) →列
関数
列sequenceと0<z1<z2< (length sequence) を満たす二つの整数z1及びz2とを与えられると,関数subseqは,
長さがz2−z1で添字がz1以上z2未満の要素を含む部分列を返す。部分列は,新たに割り当てられ,sequence
と同じクラスに属する。
要求された部分列の割当てができない場合は,エラーが発生する(エラー名cannot-create-sequence)。z1
又はz2が上の範囲外である場合は,エラーが発生する(エラー名index-out-of-range)。sequenceがベクタ若
しくはリストでない場合,z1が整数でない場合又はz2が整数でない場合は,エラーが発生する(エラー名
domain-error)。
例 (subseq "abcdef" 1 4)
⇒ "bcd"
(subseq ʼ(a b c d e f) 1 4)
⇒ (b c d)
(subseq (vector ʼa ʼb ʼc ʼd ʼe ʼf) 1 4)
⇒ #(b c d)
(map-into destination function sequence*) →列
関数
79
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数map-intoは,列sequence中の各要素に順次functionを適用し,それらの結果が含まれるように
destinationを破壊的に変更する。destinationを返す。
destination及び各sequenceがすべて同じ長さでない場合,(いずれかのsequence又はdestinationで)最も
短い列が終わったときに,繰返しが終了する。
functionの呼出しは左から右へと進む。したがって,functionが副作用をもつ場合,利用者はこの順序に
依存してよい。
destinationがベクタ又はリストでない場合は,エラーが発生する(エラー名domain-error)。sequenceの
いずれかがベクタ又はリストでない場合は,エラーが発生する(エラー名domain-error)。
例 (setq a (list 1 2 3 4))
⇒ (1 2 3 4)
(setq b (list 10 10 10 10))
⇒ (10 10 10 10)
(map-into a #ʼ+ a b)
⇒ (11 12 13 14)
a
⇒ (11 12 13 14)
b
⇒ (10 10 10 10)
(setq k ʼ(one two three))
⇒ (one two three)
(map-into a #ʼcons k a)
⇒ ((one.1)(two.12)(three.13)14)
(let ((x 0))
(map-into a
(lambda () (setq x (+ x 2)))))
⇒ (2 4 6 8)
a
⇒ (2 4 6 8)
18. ストリームクラス ストリームは,<stream>クラスのインスタンスとする。これらは,データの入力
元又は出力先の役割を果たすオブジェクトとする。
(streamp obj) →真偽値
関数
関数streampは,objがストリーム(クラス<stream>のインスタンス)である場合はtを返し,それ以外
の場合はnilを返す。objは,いかなるISLISPオブジェクトでもよい。引数がクラス<stream>のインスタン
スである場合,そのストリームが開いていても閉じていても,streampは,影響を受けない。
例 (streamp (standard-input))
⇒ t
(streamp ʼ())
⇒ nil
(open-stream-p obj) →真偽値
関数
関数open-stream-pは,objが開いているストリームである場合はtを返し,それ以外の場合はnilを返す。
(input-stream-p obj) →真偽値
関数
関数input-stream-pは,objが入力操作を扱うことができるストリームである場合はtを返し,それ以外
の場合はnilを返す。
例 (input-stream-p (standard-input))
⇒ t
(input-stream-p (standard-output))
⇒ nil
(input-stream-p ʼ(a b c))
⇒ nil
(output-stream-p obj) →真偽値
関数
80
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
関数output-stream-pは,objが出力操作を扱うことができるストリームである場合はtを返し,それ以外
の場合はnilを返す。
例 (output-stream-p (standard-output))
⇒ t
(output-stream-p (standard-input))
⇒ nil
(output-stream-p "hello")
⇒ nil
81
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(standard-input) →<stream>
関数
(standard-output) →<stream>
関数
(error-output) →<stream>
関数
関数standard-inputは,入力関数の省略時ストリームとして使用されるストリームを返す。
関数standard-outputは,出力関数の省略時ストリームとして使用されるストリームを返す。
関数error-outputは,警告及びエラーメッセージのための省略時ストリームとして使用されるストリーム
を返す。
これらの関数が返す値は,初期状態では処理系定義であるが,動的に変更できる(with-standard-input,
with-standard-output及びwith-error-output参照)。
(with-standard-input stream-form form*) →<object>
特殊演算子
(with-standard-output stream-form form*) →<object>
特殊演算子
(with-error-output stream-form form*) →<object>
特殊演算子
これらの特殊形式は,まず引数stream-formを評価してストリームSを作り,次に対応する関数
(standard-input,standard-output又はerror-output)がストリームSを返す動的環境の中でその本体form*を
評価する。これらの特殊形式の返り値は,本体の最後のformを評価した結果(formがない場合は,nil)
とする。
例 (with-standard-input (create-string-input-stream "this is a string" )
(list (read) (read)))
⇒ (this is)
18.1 ファイルへのストリーム ストリームは,ファイル又は入出力装置に接続されることがある。名前
が与えられると,その名前のファイルに接続されたストリームを作成することができる。ISLISPでは,名
前が付けられたファイルだけを取り扱う。
ファイル名 (file name) は,文字列で表現する。ファイル名の正しい構文は,処理系定義とする。
ファイルへのストリームは,open-input-file,open-output-file,open-io-file,with-open-input-file,
with-open-output-file又はwith-open-io-fileによって作成する。
(open-input-file filename [element-class]) →<stream>
関数
(open-output-file filename [element-class]) →<stream>
関数
(open-io-file filename [element-class]) →<stream>
関数
関数open-input-fileは,ファイルを入力専用に開く。関数open-output-fileは,ファイルを出力専用に開く。
関数open-io-fileは,ファイルを入出力用に開く。
filenameが文字列でない場合は,エラーが発生する(エラー名domain-error)。対応するファイルが,処
理系定義の方法で開かれる。これらの関数は,filenameで指定されたファイルに接続された<stream>クラス
のインスタンスを返す。
element-classは,要素の種類 (element class) であり,クラス<character>(省略時)であるか又は2進ス
トリームに用いられる1バイト中のビット数である正の整数のいずれかとする。すべての処理系は,8ビ
ットからなるバイト(整数0〜255を表現可能なバイト)を許さなければならないが,処理系によっては,
他のバイトサイズを許す場合がある。
備考 2進ストリームが使用された場合,バイト中のビットの順序及びワード中のバイトの順序(す
なわち,右から左か又は左から右か)は,それぞれ処理系定義とする。
82
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
例 (open-input-file "example.lsp" 8)
⇒ 処理系定義
(with-open-input-file (name filename [element-class]) form*) →<object>
特殊演算子
(with-open-output-file (name filename [element-class]) form*) →<object>
特殊演算子
(with-open-io-file (name filename [element-class]) form*) →<object>
特殊演算子
これらの特殊形式は,(それぞれopen-input-file,open-output-file又はopen-io-fileを使用して)ファイル
ヘのストリームを開き,form*を評価し,ファイルを閉じ,そして最後のformによって返される値(form
がない場合は,nil)を返す。
filename及びelement-classは,評価され,ファイルを開く関数に引数として渡される。ファイルを開く
ことによって作成されたストリームは,nameという名前の変数に(letが使用されたかのように)束縛さ
れる。したがって,識別子nameを使ってストリームを参照することができる。
これらの特殊形式の実行が終了する際に,その終了が正常かどうかにかかわらず,ストリームは閉じら
れる。この理由によって,ファイルを開閉する関数よりも,通常はこれらの特殊形式を使うことが多い。
例 (with-open-output-file (outstream "example.dat")
(format outstream "hello"))
⇒ nil
(with-open-input-file (instream "example.dat")
(read instream))
⇒ hello
(close stream) →処理系定義
関数
関数closeは,ストリームstreamを閉じる。streamが閉じられた場合,入力操作又は出力操作に用いる
ことはできない。ファイルに対するstreamを閉じると,streamとそのファイルとの関係は終了する。stream
が既に閉じられていた場合,この関数は,何もしない。結果の値は,処理系定義とする。streamがストリ
ームでない場合は,エラーが発生する(エラー名domain-error)。
例 (defglobal input-str (open-input-file "data.lsp"))
⇒ input-str
(close input-str)
⇒ 処理系定義
(close input-str)
⇒ 処理系定義
(finish-output stream) →<null>
関数
関数finish-outputは,streamで指示される出力先への,保留中の出力を出す。保留中の出力が終わるま
で待ち,nilを返す。例えば,保留中の出力がバッファに格納されている場合,finish-outputは,ストリー
ムの行き先に出力するようバッファに命令する。streamが出力操作を扱えるストリームでない場合は,エ
ラーが発生する(エラー名domain-error)。
例 (defglobal output-str (open-output-file "data.lsp")) ⇒ output-str
(finish-output output-str)
⇒ nil
18.2 その他のストリーム 次の関数によって,ファイル以外のストリームを作成できる。
create-string-input-stream create-string-output-stream
文字列ストリームは,文字列に対するストリームとする。入力では,入力関数が,入力文字列から得ら
れる文字の並びからオブジェクトを生成する。出力では,出力関数が文字の並びを生成し,出力文字列に
格納する。
83
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(create-string-input-stream string) →<stream>
関数
関数create-string-input-streamは,stringからの入力ストリームを作成し,それを値として返す。
stringが文字列でない場合は,エラーが発生する(エラー名domain-error)。
例 (let ((str (create-string-input-stream "this is a string")))
(list (read str) (read str) (read str)))
⇒ (this is a)
(create-string-output-stream) →<stream>
関数
関数create-string-output-streamは,文字列出力ストリームを作成し,それを値として返す。文字列ストリ
ームへの出力は,get-output-stream-stringによって取り出すことができる。
例 (let ((str (create-string-output-stream)))
(format str "hello")
(format str "world")
(get-output-stream-string str))
⇒ "helloworld"
(get-output-stream-string stream) →<string>
関数
関数get-output-stream-stringは,streamに対し,この関数の最後の呼出し以降出力されたすべての文字を
含む文字列を返す。この関数が以前にstreamを引数として呼び出されていない場合は,ストリームの作成
以降出力されたすべての文字を含む文字列を返す。streamがcreate-string-output-streamによって作成された
ストリームでない場合は,エラーが発生する(エラー名domain-error)。
例 (let ((out-str (create-string-output-stream)))
(format out-str "This is a string")
(let ((part1 (get-output-stream-string out-str)))
(format out-str "right!")
(list part1 (get-output-stream-string out-str))))
⇒ ("This is a string" "right!")
19. 入出力
19.1 入力関数の引数についての共通事項 入力を行う入力関数の多くは,引数を次のとおり扱う。
ストリームの終わりに到達した場合(すなわち,ストリームの最後の要素の次の要素を読み込もうとし
た場合),動作はeos-error-pの値(省略時値はt)に依存する。eos-error-pがnilであった場合は,入力関数
はeos-value(省略時値はnil)を返し,それ以外の場合はエラーが発生する(エラー名end-of-stream)。
input-streamが指定されていない場合は,標準入力ストリーム(関数standard-inputの返す値)を用いる。
input-streamが述語input-stream-pを満たさない場合は,エラーが発生する(エラー名not-an-input-stream)。
19.2 文字入出力 文字の入出力には,次の操作を用いる。文字入出力操作を扱えないストリームに対し,
これらの操作を行おうとした場合は,エラーが発生する。
(read [input-stream [eos-error-p [eos-value]]]) →<object>
関数
関数readは,ストリームinput-streamからISLISPオブジェクトのテキスト表現を読み込み,そのISLISP
84
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
オブジェクトを返す。
input-stream,eos-error-p及びeos-valueの意味は,19.1による。
例 (defglobal str (create-string-input-stream "hello" #(1 2 3) 123 #\\A"))
⇒ str
(read str)
⇒ hello
(read str)
⇒ # (1 2 3)
(read str)
⇒ 123
(read str)
⇒ #\A
(read str nil "the end")
⇒ "the end”
(read-char [input-stream [eos-error-p [eos-value]]]) →<object>
関数
関数read-charは,input-streamから1文字を読み込み,これに対応する文字オブジェクトを返す。
input-stream,eos-error-p及びeos-valueの意味は,19.1による。
例 (defglobal str (create-string-input-stream "hi"))
⇒ str
(read-char str)
⇒ #\h
(read-char str)
⇒ #\i
(read-char str) エラーが発生する。
(preview-char [input-stream [eos-error-p [eos-value]]]) →<object>
関数
関数preview-charは,input-streamの次の文字を(もしあれば)返す。その文字は消費されない。つまり,
次にそのストリームから文字を読んだ場合には,同じ文字が現れる。
input-stream,eos-error-p及びeos-valueの意味は,19.1による。
例 (let ((s (create-string-input-stream "foo")))
(list (preview-char s) (read-char s) (read-char s)))
⇒ (#\f #\f #\o)
(read-line [input-stream [eos-error-p [eos-value]]]) →<object>
関数
関数read-lineは,input-streamから1行分の文字を読み込み,これを文字列として返す(行の最後の復帰
改行文字は含まない。)。次の復帰改行文字より前にストリームの終わりに到達した場合,終わりに到達す
るまでに読み込んだ行が空行でなかったときは,その行を返す。
input-stream,eos-error-p及びeos-valueの意味は,19.1による。
例 (with-open-output-file (out "newfile")
(format out "This is an example")
(format out "〜%")
(format out "look at the output file"))
⇒ nil
(defglobal str (open-input-file "newfile"))
⇒ str
(read-line str)
⇒ "This is an example"
(read-line str)
⇒ "look at the output file"
85
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(stream-ready-p input-stream) →真偽値
関数
関数stream-ready-pは,streamから次の要素を得ようとしたときに,処理系が待ち状態に入らない場合は
tを返し,それ以外の場合はnilを返す。streamが入力操作可能なストリームでない場合は,エラーが発生
する(エラー名domain-error)。
例 (with-open-output-file (out "testfile.dat")
(format out "This is an example"))
⇒ nil
(with-open-input-file (in "testfile.dat")
(stream-ready-p in))
⇒ t
(format output-stream format-string obj*) →<null>
関数
(format-char output-stream char) →<null>
関数
(format-float output-stream float) →<null>
関数
(format-fresh-line output-stream) →<null>
関数
(format-integer output-stream integer radix) →<null>
関数
(format-object output-stream obj escape-p) →<null>
関数
(format-tab output-stream column) →<null>
関数
関数formatは,format-stringに従って印字をするという副作用をもつ。返り値は,nilとする。引数
outoput-streamが,述語output-stream-pを満たさない場合は,エラーが発生する(エラー名
not-an-output-stream)。format-stringが文字列でない場合は,エラーが発生する(エラー名domain-error)。
formatの書式指定を次に示す。ここで,objは,formatの引数obj*の中の,次に印字すべき引数を指す。
〜A
整形 (aesthetic) : objは,いかなるオブジェクトでもよい。objは,〜Sの場合と同様に印字さ
れるが,エスケープ文字は印字されない。文字は,変換されずに直接出力される。すなわち,
この書式指定が生成する出力は,人間が読むのに適している。
これは,(format-object output-stream obj nil) によって実装される。
〜B
2進 (binary) : objが整数でない場合は,エラーが発生する。objは,2進数で印字される。
これは,(format-integer output-stream obj 2) によって実装される。
〜C
文字 (character) : objが文字でない場合は,エラーが発生する。objは,変換されずに直接出
力される。
これは,(format-char output-stream obj) によって実装される。
〜D
10進 (decimal) : objが整数でない場合は,エラーが発生する。objは,10進数で印字される。
これは,(format-integer output-stream obj 10) によって実装される。
〜G
一般的な浮動小数点数 (general floating-point number) : objが数値でない場合は,エラーが発生
する。Objは,浮動小数点数として印字される。
これは,(format-float output-stream obj) によって実装される。
〜O
8進 (octal) : objが整数でない場合は,エラーが発生する。objは,8進数で印字される。
これは,(format-integer output-stream obj 8) によって実装される。
〜nR
基数 (radix) : objが整数でない場合は,エラーが発生する。objは,n進数 (2<n<36) で印字さ
れる。
86
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
これは,(format-integer output-stream obj n) によって実装される。
〜S
S式:objは,いかなるオブジェクトでもよい。この書式指定は,必要であればエスケープ文
字とともに,objのテキスト表現を出力する。すなわち,この書式指定の生成する出力は,関数
readへの入力として適している。
これは,(format-object output-stream obj t) によって実装される。
〜nT
タブ (tab) : 第nけたへ移動するための空白文字を出力する(ここで,第0けたとは,左マー
ジンのこととする。)。既に第nけた又はそれ以降に達していた場合,空白文字を一つ出力する。
処理系が現在のけたの位置を決定できない場合,その動作は処理系定義とするが,少なくとも
一つの空白文字を出力する。
これは,(format-tab output-stream n) によって実装される。
〜X
16進 (hexadecimal) : objが整数でない場合は,エラーが発生する。objは,16進数で印字され
る。
これは,(format-integer output-stream obj 16) によって実装される。
〜%
復帰改行:#\newline文字を,出力する。
これは,(format-char output-stream #\newline) によって実装される。
〜&
条件付き復帰改行:出力ストリームが行の先頭にあると決定できない場合に,#\newline文
字を出力する。
これは,(format-fresh-line output-stream) によって実装される。
〜〜
チルダ:チルダ (〜) を出力する。
これは,(format-char output-stream #\〜) によって実装される。
例 (format output-stream "No result")
⇒ nil
出力:No result
(format output-stream "The result is 〜A and nothing else." "meningitis")
⇒ nil
出力:The result is meningitis and nothing else.
(format output-stream "The result i〜C" #\s)
⇒ nil
出力:The result is
(format output-stream "The results are 〜S and 〜S." 1 #\a)
⇒ nil
出力:The results are 1 and #\a.
(format output-stream "Binary code 〜B" 150)
⇒ nil
出力:Binary code 10010110
(format output-stream "permission 〜O" 493)
⇒ nil
出力:permission 755
87
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(format output-stream "You 〜X 〜X" 2989 64206)
⇒ nil
出力:You BAD FACE
(progn
(format output-stream "〜&Name 〜10Tincome 〜20Ttax ~%")
(format output-stream "〜A 〜10T〜D 〜20T〜D" "Grummy" 23000 7500)) ⇒ nil
出力:Name income tax
Grummy 23000 7500
(format output-stream "This will be split into 〜%two lines.") ⇒ nil
出力:This will be split into
two lines.
(format output-stream "This is a tilde: 〜〜")
⇒ nil
出力:This is a tilde: 〜
19.3 2進入出力 2進入出力には次の操作を用いる。2進入出力操作を扱えないストリームに対し,これ
らの操作を行おうとした場合は,エラーが発生する。
(read-byte input-stream [eos-error-p [eos-value]]) →<integer>
関数
関数read-byteは,input-streamから1バイトを読み込み,それを返す。1バイト中のビット数は,input-stream
の要素の種類によって決定される(open-input-file参照)。
input-stream, eos-error-p及びeos-valueの意味は,19.1による。
例 ;; この例では,8ビットの文字コードが,ファイルに格納されるものと仮定する。
(defglobal byte-example (open-output-stream "byte-ex")) ⇒ byte-example
(format byte-example "hello")
⇒ nil
(close byte-example)
⇒ 処理系定義
(setq byte-example (open-input-stream "byte-ex" 8))
⇒ 処理系定義
(read-byte byte-example)
⇒ 104 (処理系定義)
(read-byte byte-example)
⇒ 101 (処理系定義)
(read-byte byte-example)
⇒ 108 (処理系定義)
(read-byte byte-example)
⇒ 108 (処理系定義)
(read-byte byte-example)
⇒ 111 (処理系定義)
(write-byte z output-stream) →<integer>
関数
関数write-byteは,zをoutput-streamに書き,そのzを返す。zがoutput-streamの要素の種類に適した範
囲の整数でない場合又はoutput-streamが出力操作を扱えるストリームでない場合は,エラーが発生する(エ
ラー名domain-error)。
例 (let ((out-str (open-output-stream "byte-example" 8)))
(write-byte #b101 out-str)
(close out-str))
⇒ 処理系定義
88
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
20. ファイル
(probe-file filename) →真偽値
関数
関数probe-fileは,filenameによって指定されたファイルが存在する場合はtを返し,それ以外の場合は
nilを返す。filenameが文字列でない場合は,エラーが発生する(エラー名domain-error)。
例 (probe-file "notexist.lsp")
⇒ nil
(defglobal new-file (open-output-file "notexist.lsp"))
⇒ new-file
(close new-file)
⇒ 処理系定義
(probe-file "notexist.lsp")
⇒ t
(file-position stream) →<integer>
関数
関数file-positionは,streamに付随するファイル位置 (file position) を返す。
ファイル位置は,ストリーム中の位置を表す非負整数とする。2進ストリームの場合,ファイル位置は,
ストリーム中の先行するバイト数を表す。次の式のいずれかを実行するたびに,ファイル位置は1ずつ増
加する。
(read-byte stream)
(write-byte z stream)
文字ストリームの場合,ファイル位置は,次の式のいずれかを実行するたびに増加する。その増分値は,
処理系定義の非負整数とする。
(format stream...)
(format-char stream char)
(format-float stream float)
(format-fresh-line stream)
(format-integer stream integer radix)
(format-object stream obj escape-p)
(format-tab stream column)
(report-condition condition stream)
(read-char stream)
(read-line stream)
(read stream)
増分値は,出力及びファイル位置に依存する。どの整数がファイルの第1要素を表すかは,処理系定義
とする。streamがファイルへのストリーム又はファイルからのストリームでない場合は,エラーが発生す
る(エラー名domain-error)。
例 ;; この例では,8ビットの文字コードが,ファイルに格納されるものと仮定する。
(defglobal example (open-output-file "example.lsp")) ⇒ example
(format example "hello")
⇒ nil
(close example)
⇒ 処理系定義
(setq example (open-input-stream "example.lsp" 8))
⇒ 処理系定義
(file-position example)
⇒ 0 (処理系定義)
(read-byte example)
⇒ 104 (処理系定義)
89
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(file-position example)
⇒ 1 (処理系定義)
(set-file-position stream z) →<integer>
関数
関数set-file-positionは,ストリームstreamのファイル位置(file-position参照)を,zに変更しようとす
る。正確にzの位置に移動することができない場合,ファイル内で処理系定義の動作が実行される。zの
位置に移動できた場合でも,移動できなかった場合でも,返される値は新しいファイル位置とする。
streamがファイルへのストリームでもファイルからのストリームでもない場合,又はzが非負整数でな
い場合は,エラーが発生する(エラー名domain-error)。
例 (set-file-position example 4)
⇒ 4
(file-length filename element-class) →<object>
関数
関数file-lengthは,filenameによって指定されたファイルの長さを返す。長さが決定できない場合は,nil
を返す。element-classは,要素の種類(18.1参照)を指定する。filenameが文字列でない場合は,エラーが
発生する(エラー名domain-error)。
例 (file-length "file27.dat" 8)
⇒ 25
;; 処理系は,2ビットからなるバイトを実装する必要はない。
(file-length "file27.dat" 2)
⇒ 100
21. 例外処理機能 例外処理機能は,エラー処理機能 (error system) とも呼ばれる。実行時に何らかの問
題が検出されたとき,適合するプログラムの制御の下でその状態を表現し,解決する手段を,例外処理機
能が提供する。
21.1 例外状態 問題が検出されたとき,その状況を表現する例外状態 (condition) が生成され,例外状態
によって表された状況が,通知 (signaling) と呼ぶ処理によって伝えられる。この通知処理は,動的に設定
されるハンドラ (handler) に,問題を解決する機会を与える。通常のISLISPオブジェクトであることを強
調するために,例外状態は,例外オブジェクト (condition object) とも呼ばれる。
図1に,例外状態クラスに関する継承関係を示す。
幾つかの例外状態クラスに対しては,インスタンス生成時に,そのインスタンスに付随するデータ(21.3
参照)を与えるために,createが初期化引数を要求する。
実行的に検出されるプログラム誤りを表す例外状態は,エラー (error) と呼ぶ。エラー及び処理系の制
約を表す例外状態を総称して,重大な例外状態 (serious condition) と呼ぶ。
備考 LISPの方言によっては,“重大でない”例外状態の考え方をもつものがある。そのような例外
状態は,この規格の範囲を超えている。したがって,ここでは,最も一般的な例外状態クラス
として,<serious-condition>を使用する。
21.2 例外状態の通知及び扱い 例外状態が通知されたとき,状況を表す例外オブジェクトをただ一つの
引数として活性ハンドラ (active handler) が起動される。初期の活性ハンドラは,システムによって生成さ
れている。このハンドラの動作は,処理系定義(例えば,最上位へ戻る,プログラムを終了する,対話型
デバッガに入るなど)とする。利用者のプログラムが,ハンドラを生成してもよい(with-handler参照)。
ある時点では,ただ一つのハンドラが活性であるものとする。with-handlerで新しいハンドラを生成する
と,前の活性ハンドラは遮へいされる。この新しく生成されたハンドラは,別のwith-handlerの利用によ
90
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
って遮へいされない限り,それが付随するコード本体の実行中,活性であるものとする。
ハンドラ関数が呼び出されると,signal-conditionが呼び出された時点の動的環境において実行を行う。
ただし,ハンドラ全体の状態は,呼び出されたハンドラ関数が活性ハンドラとして設定された時点の状態
に戻る。
備考 これは,ハンドラの実行中にエラーが起きても,そのハンドラ自身がエラーを処理することを
期待されていないことを意味する。ハンドラがそれ自身の実行中のエラーを処理する必要があ
れば,関数定義にlabelsを利用し,ハンドラ関数の本体内で自分自身をハンドラとして再設定
すればよい。
ハンドラは,その実行終了時に,signal-conditionの呼出しの外側へ制御を移行しなければならない。そ
のような制御の移行は,go,throw若しくはreturn-fromの利用によって明示的に行われるか,又は,これ
らと同等の効果をもつcontinue-conditionの利用によって行われなければならない。ハンドラが正常に戻る
場合は,結果は未定義とする。ハンドラは,必ず制御を移行する。
ハンドラは,引数として受け取った例外オブジェクトをsignal-conditionに受け渡すことによって,他の
ハンドラに例外処理を委任してもよい。
21.2.1 例外通知に関する操作
(error error-string obj*) →<object>
関数
関数errorは,エラーを通知する。
error-string及び一連のobjは,formatに与えられるとエラーメッセージを生成するが,これらの引数が
使われるかどうかは,処理系定義とする。
これは,次と同値とする。
(signal-condition
(create (class <simple-error>)
ʼformat-string error-string
ʼformat-arguments (list obj*)))
nil)
(cerror continue-string error-string obj*) →<object>
関数
関数cerrorは,errorと似ているが,通知されるエラーは継続可能(continue-condition参照)とする。引
数continue-stringは,この関数が戻る場合に何が起こるかを記述する文字列とする。
これは,次と同値とする。
(signal-condition
(create (class <simple-error>)
ʼformat-string error-string
ʼformat-arguments (list obj*)))
(let ((str (create-string-output-stream)))
(format str continue-string obj*)
(get-output-stream-string str)))
(signal-condition condition continuable) →<object>
関数
関数signal-conditionは,conditionを処理するために,例外処理機能を呼び出す。
continuableがnilのとき,継続(continue-condition参照)しようとした場合の結果は,未定義とする。こ
91
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
の場合,signal-conditionの呼出しは正常には戻らない。
continuableがnilでない場合,signal-conditionの呼出しから戻ることができる(continue-condition参照)。
この場合,continuableの値は,継続の結果を記述する文字列又は記号tとする。後者の場合,"Continue with
no special action." といった処理系定義の文字列が利用される。
例 (signal-condition (create (class <simple-error>)
ʼformat-string "A 〜A problem occurred."
ʼformat-arguments ʼ(bad))
nil)
21.2.2 例外処理に関する操作
(ignore-error form*) →<object>
特殊演算子
特殊形式ignore-errorsは,form*の実行中にエラーが発生した場合,ignore-errorsが直ちにnilを返すよう
な,<error>クラスに対するハンドラを生成する。その後,form*を左から右に順に実行し,実行が正常に終
了した場合,最後のformが返す値(formがない場合は,nil)を返す。
(report-condition condition stream) →<condition>
包括関数
包括関数report-conditionは,conditionの自然言語による記述をstreamに出力する。この包括関数は,利
用者定義の例外状態クラスに対して特殊化してもよい。
(condition-continuable condition) →<object>
関数
関数condition-continuableは,conditionが継続可能でない場合はnilを返し,継続可能であれば,継続の
結果を記述する文字列を返す。
(continue-condition condition [value])制御の移行及びデータの転送
関数
関数continue-conditionは,conditionを通知したsignal-conditionの呼出しを探し,その呼出しがvalueを
値として正常に戻るための処理を行うことによって,そのsignal-conditionの呼出し以降の実行を継続する
(continue)。valueの省略時値は,nilとする。
conditionが継続可能でない場合は,結果は未定義とする。
(with-handler handler form*) →<object>
特殊演算子
特殊形式with-handlerは,まずhandlerを評価する。その値は,関数でなければならない。この関数をハ
ンドラ関数 (handler function) と呼ぶ。このハンドラ関数は活性ハンドラ(21.2参照)として設定され,そ
の後form*が左から右に順に評価される。すべてのformの評価が正常に終了した場合,最後のformの値を
返す。formがない場合は,nilを返す。
21.3 例外オブジェクトに付随するデータ ISLISPで定義される例外状態クラスの幾つかに対しては,例
外オブジェクトの生成時にそのオブジェクトに付随するデータを与え,後で取り出すことができる。その
ようなクラスに対する初期化引数及びアクセス関数を,ここで定義する。
21.3.1 算術エラー
<arithmetic-error> operation operation
operands operands
ここで,operationは実行されていた関数であり,operandsは受け取った
引数のリストとする。
(arithmetic-error-operation arithmetic-error) →<function>
関数
92
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
(arithmetic-error-operands arithmetic-error) →<list>
関数
これらの関数は,arithmetic-error生成時に,データとして与えられたoperation及びoperandsをそれぞれ
返す。arithmetic-errorがクラス<arithmetic-error>の例外状態でない場合は,エラーが発生する(エラー名
domain-error)。
21.3.2 定義域エラー
<domain-error> object object
expected-class expected-class
ここで,objectは実際に与えられたオブジェクトであり,expected-class
は期待されるクラスとする。
(domain-error-object domain-error) →<object>
関数
(domain-error-expected-class domain-error) →<class>
関数
これらの関数は,domain-error生成時に,データとして与えられたobject及びexpected-classをそれぞれ
返す。domain-errorがクラス<domain-error>の例外状態でない場合は,エラーが発生する(エラー名
domain-error)。
21.3.3 構文解析エラー
<parse-error> string string
expected-class expected-class
ここで,stringは構文解析中の文字列であり,expected-classはstring中の
テキストが表現することを期待されるクラスとする。
(parse-error-string parse-error) →<string>
関数
(parse-error-expected-class parse-error) →<class>
関数
これらの関数は,parse-error生成時に,データとして与えられたstring及びexpected-classをそれぞれ返
す。parse-errorがクラス<parse-error>の例外状態でない場合は,エラーが発生する(エラー名domain-error)。
21.3.4 単純なエラー
<simple-error> format-string format-string
format-arguments format-arguments
ここで,format-string及びformat-argumentsは,エラーメッセージを作成
するためにformatに渡される文字列及びオブジェクトのリストとする。
format-argumentsとして与えられたリスト中の各オブジェクトは,format
の呼出しに対する個別の引数となる。
(simple-error-format-string simple-error) →<string>
関数
(simple-error-format-arguments simple-error) →<list>
関数
これらの関数は,simple-error生成時に,データとして与えられたformat-string及びformat-argumentsを
それぞれ返す。simple-errorがクラス<simple-error>の例外状態でない場合は,エラーが発生する(エラー名
domain-error)。
21.3.5 ストリームエラー
93
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
<stream-error> stream stream
ここで,streamは,エラーが生じたストリームとする。
(stream-error-stream stream-error) →<stream>
関数
関数stream-error-streamは,stream-error生成時に,データとして与えられたstreamを返す。stream-error
がクラス<stream-error>の例外状態でない場合は,エラーが発生する(エラー名domain-error)。
21.3.6 未定義実体のエラー
<undefined-entity> name name
namespace namespace
ここで,nameは,未定義であった識別子を表す記号とする。namespace
は,記号variable,dynamic-variable,function又はclassのいずれかとする。
(undefined-entity-name undefined-entity) →<symbol>
関数
(undefined-entity-namespace undefined-entity) →<symbol>
関数
これらの関数は,undefined-entity生成時に,データとして与えられたname及びnamespaceを返す。
undefined-entityがクラス<undefined-entity>の例外状態でない場合は,エラーが発生する(エラー名
domain-error)。
undefined-entity-namespaceの結果は,記号variable,dynamic-variable,function又はclassのいずれかとす
る。
21.4 エラー名 この規格で名前を付けたエラー及びその意味を次に示す。
arity-error 関数の定義で許容されるパラメタ数に適合しない個数の引数を使って関
数が起動される場合に,このエラーが発生する。このエラーは,クラス
<program-error>の例外状態として表される。
cannot-create-array このエラーは,割り当てることができない配列を割り当てる場合に,発
生する。このエラーは,クラス<storage-exhausted>の例外状態として表さ
れる。
cannot-create-cons このエラーは,割り当てることができないコンスを割り当てる場合に,
発生する。このエラーは,クラス<storage-exhausted>の例外状態として表
される。
cannot-create-list このエラーは,割り当てることができないリストを割り当てる場合に,
発生する。このエラーは,クラス<storage-exhausted>の例外状態として表
される。
cannot-create-sequence このエラーは,列を生成する関数(例えば,subseq)がその列を割り当
てられない場合に,発生する。このエラーは,クラス<storage-exhausted>
の例外状態として表される。
cannot-create-string このエラーは,割り当てることができない文字列を割り当てる場合に,
発生する。このエラーは,クラス<storage-exhausted>の例外状態として表
される。
cannot-create-vector このエラーは,割り当てることができないベクタを割り当てる場合に,
94
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
発生する。このエラーは,クラス<storage-exhausted>の例外状態として表
される。
cannot-parse-number このエラーは,parse-number関数が受け取ったstirng引数が数値のテキス
ト表現でない場合に,発生する。このエラーは,クラス<parse-error>の例
外状態として表される。
control-error このエラーは,ブロックから2回以上出ようとした場合,又は捕そくタ
グに対するcatch形式がない場合に,発生する。このエラーは,クラス
<control-error>の例外状態として表される。
division-by-zero このエラーは,ゼロで割ろうとした場合に発生する。このエラーは,ク
ラス<division-by-zero>の例外状態として表される。
domain-error このエラーは,引数クラスの制約をもつ標準関数に,引数として与えら
れたオブジェクトが,要求されるクラスのインスタンスでない場合に,
発生する。このエラーは,クラス<domain-error>の例外状態として表され
る。
end-of-stream eos-error-p引数が真のときに,ストリームの終端で文字若しくはバイト
を読もうとした場合,又はreadやread-lineがオブジェクトを読もうとし
ており,かつそのオブジェクトの読込みが終わる前にストリームの終端
が現れた場合に,このエラーは,発生する。このエラーは,クラス
<end-of-stream>の例外状態として表される。
immutable-binding このエラーは,変更不可能な束縛を変更しようとする場合に,発生する。
このエラーは,クラス<program-error>の例外状態として表される。
improper-argument-list このエラーは,apply関数に与えられた最後の引数がnilで終わるリスト
でない場合に,発生する。このエラーは,クラス<program-error>の例外
状態として表される。
index-out-of-range このエラーは,(eltのような)列中の要素をアクセスする関数に与えら
れた添字が,列の範囲を超えた整数である場合に,発生する。このエラ
ーは,クラス<program-error>の例外状態として表される。
not-an-input-stream このエラーは,入力ストリームでないストリームから入力しようとした
場合に,発生する。このエラーは,クラス<domain-error>の例外状態とし
て表される。
not-an-output-stream このエラーは,出力ストリームでないストリームに出力しようとした場
合に,発生する。このエラーは,クラス<domain-error>の例外状態として
表される。
unbound-variable このエラーは,未束縛の変数をアクセスした場合に,発生する。このエ
ラーは,クラス<unbound-variable>の例外状態として表される。
undefined-entity このエラーは,識別子によって示される実体が存在しないときに,その
実体をアクセスした場合に,発生する。このエラーは,クラス
<undefined-entity>の例外状態として表される。
undefined-function このエラーは,関数がその起動時点で存在しない場合に,発生する。こ
のエラーは,クラス<undefined-function>の例外状態として表される。
95
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
発生しうる幾つかのエラーは,この規格では名前を付けていない。また,処理系によって追加されるエ
ラーもある。上のエラーが,起こりうるエラーのすべてではない。
22. その他の機能
(identity obj) →<object>
関数
関数identityは,objとeqlであるオブジェクトを返す。objは,いかなるISLISPオブジェクトでもよい。
例 (identity ʼ(a b c))
⇒ (a b c)
(get-universal-time) →<integer>
関数
関数get-universal-timeは,世界標準時の形で“現在の時刻”の近似値を返す。単位は秒とする。世界標
準時は,1900年1月1日の始まり(すなわち,午前0時)からの秒数(うるう秒は無視する。)を表す整
数とする。get-universal-timeが2回呼び出される場合,最初の値は2回目の値以下とする。
処理系は,返される時刻が正しいことを確認する方法を備える必要はない。しかし,返される時刻が正
しくないと処理系が判断できる(例えば,時計がまだ初期化されていないことを決定できる)場合は,エ
ラーが発生する。
例 (get-universal-time)
⇒ 2901312000
(get-internal-real-time) →<integer>
関数
(get-interna1-run-time) →<integer>
関数
関数get-internal-real-timeは,現在の時刻を表す整数を返す。この値は,ある基準時刻からの相対時間と
し,単位は内部時間単位(internal-time-units-per-second参照)とする。この関数を2回呼び出したときの値
の差は,2回の呼出しの間の実際の経過時間とする。
関数get-internal-run-timeは,現在の実行時間を表す整数を返す。単位は内部時間単位とする。この時間
の正確な意味は,処理系定義とする。この関数を2回呼び出したときの値の差は,その間にプログラム実
行のために費やされた時間とする。
(internal-time-units-per-second) →<integer>
関数
関数internal-time-units-per-secondは,処理系の内部時間単位の1秒当たりの個数を返す。
96
X 3012 : 1998 (ISO/IEC 13816 : 1997)
2019年7月1日の法改正により名称が変わりました。まえがきを除き,本規格中の「日本工業規格」を「日本産業規格」に読み替えてください。
プログラミング言語ISLISP JIS原案作成委員会 構成表(敬称略・順不同)
氏名
所属
(委員長)
湯 淺 太 一
京都大学
(幹事)
岸 田 克 己
日本電信電話株式会社
(委員)
浅 井 登
株式会社富士通静岡エンジニアリング
伊 藤 貴 康
東北大学
梅 村 恭 司
豊橋技術科学大学
橋 爪 邦 隆
工業技術院
黒 川 利 明
日本アイ・ビー・エム株式会社
徳 永 英 二
TOK
長 坂 篤
沖電気工業株式会社
橋 本 繁 晴
財団法人日本規格協会
橋 本 ユキ子
日本電気株式会社
山 崎 憲 一
日本電信電話株式会社
(事務局)
三 田 真 弓
社団法人情報処理学会
(オブザーバ)
白 倉 悟 子
津田塾大学