This is Info file r5rsj.info, produced by Makeinfo version 1.68 from the input file r5rsj.texi.  File: r5rsj.info, Node: Numerical operations, Next: Numerical input and output, Prev: Syntax of numerical constants, Up: Numbers 数値演算 -------- 数値ルーチンに渡す引数の型に関する制限の指定に使用される命名規約については、*Note Entry format::に要約を載せている。本節に使用する例では、*完全*数の記法を使用して書かれたあらゆる数値定数は、*完全*数として表現されると仮定している。例によっては、*不完全*数の記法を使用して書かれた数値定数は、精度を失わずに表現できると仮定しているものもある。*不完全*数値定数は、不完全数の表現にflonumを使用する処理系でおそらく正しくなるように選択された。 [[手続き]] (number? obj) [[手続き]] (complex? obj) [[手続き]] (real? obj) [[手続き]] (rational? obj) [[手続き]] (integer? obj) 上記の数値型述語手続きは、数値以外のものを含むあらゆる種類の引数に適用できる。オブジェクトが名前を指定された型であれば#tを返し、それ以外の場合は#fを返す。一般に数についてのある型の述語手続きが真であれば、その数についての上位の述語手続きも真である。 したがって数についてのある型の述語手続きが偽であれば、その数についての下位の述語手続きも偽である。 zを不完全な複素数とすれば、`(zero? (imag-part z))'が真の場合にのみ`(real? z)'は真である。zが不完全な実数の場合は、`(= x (round x))'が真ならばその場合にのみ`(integer? x)'は真である。 (complex? 3+4i) => #t (complex? 3) => #t (real? 3) => #t (real? -2.5+0.0i) => #t (real? #e1e10) => #t (rational? 6/10) => #t (rational? 6/3) => #t (integer? 3+0i) => #t (integer? 3.0) => #t (integer? 8/4) => #t 注: *不完全*数に関しては誤差によって結果が変わる場合があるために、上記の型述語手続きの振舞いは信頼できない。 注: 多くの処理系では`rational?'手続きは`real?'手続きと、`complex?'手続きは`number?'手続きと等しくなる。ただし特殊な処理系ではある種の無理数を正確に表現できたり、複素数以外のある種の数をサポートするように数体系を拡張する場合がある。 [[手続き]] (exact? z) [[手続き]] inexact? z) 以上の数値述語手続きは、量の完全性をテストするものである。Schemeのいかなる数も、この述語手続きのいずれか一つが正確に真になる。 [[手続き]] (= z1 z2 z3 ...) [[手続き]] (< x1 x2 x3 ...) [[手続き]] (> x1 x2 x3 ...) [[手続き]] (<= x1 x2 x3 ...) [[手続き]] (>= x1 x2 x3 ...) 以上の手続きは引数がそれぞれ、等しいか、単調に増加するか、単調に減少するか、単調に減少しないか、単調に増加しない場合に#tを返す。 これらは推移的(1)でなければならない。 注: 従来のLispライクな言語に実装された上記の述語手続きは、推移的ではない。 注: 上記述語手続きを使用して不完全数を比較することはエラーではないが、小さな誤差で結果が変わる場合があるために、その結果は信頼できない。疑いがある時は数値アナリストに相談してほしい。 [[ライブラリ手続き]] (zero? z) [[ライブラリ手続き]] (positive? x) [[ライブラリ手続き]] (negative? x) [[ライブラリ手続き]] (odd? n) [[ライブラリ手続き]] (even? n) 以上の数値述語手続きは、数が特定の属性を持つかどうかをテストして#tか#fを返す。上記の注参照。 [[ライブラリ手続き]] (max x1 x2 ...) [[ライブラリ手続き]] (min x1 x2 ...) 以上の手続きは引数の中の最大値か最小値を返す。 (max 3 4) => 4 ; 完全数 (max 3.9 4) => 4.0 ; 不完全数% 注: 引数の中に不完全数が存在する場合は、(誤差が結果を変えるほど大きくないことを手続きが証明できない限り--これは特殊な処理系でのみ可能である)結果も不完全数になる。完全性が混在する数の比較に`min'もしくは`max'を使用して、かつ精度を失わずに不完全数として結果の値を表現することができない場合は、手続きは実装上の制限の侵害を報告することができる。 [[手続き]] (+ z1 ...) [[手続き]] (* z1 ...) 上記手続きは引数の和もしくは積を返す。 (+ 3 4) => 7 (+ 3) => 3 (+) => 0 (* 4) => 4 (*) => 1 [[手続き]] (- z1 z2) [[手続き]] (- z) [[オプション手続き]] (- z1 z2 ...) [[手続き]] (/ z1 z2) [[手続き]] (/ z) [[オプション手続き]] (/ z1 z2 ...) (- 3 4) => -1 (- 3 4 5) => -6 (- 3) => -3 (/ 3 4 5) => 3/20 (/ 3) => 1/3 [[ライブラリ手続き]] (abs x) `abs'は引数の大きさを返す。 (abs -7) => 7 [[手続き]] (quotient n1 n2) [[手続き]] (remainder n1 n2) [[手続き]] (modulo n1 n2) 以上の手続きは整数論的な(もしくは整数の)除算を実装するものである。n2はゼロであってはならない。手続きは3つとも整数を返す。n1/n2が整数ならば次が成立する。 (quotient n1 n2) => n1/n2 (remainder n1 n2) => 0 (modulo n1 n2) => 0 n1/n2が整数でないならば次が成立する。 (quotient n1 n2) => n_q (remainder n1 n2) => n_r (modulo n1 n2) => n_m ただしn_qはゼロ側に丸めたn1/n2。0 < |n_r| < |n2|、0 < |n_m| < |n2|とする。n_rとn_mはn1からn2の倍数だけ異なり、n_rの符号はn1に同じく、n_mの符号はn2に同じとする。 以上から整数n1とn2について、n2がゼロに等しくないとすれば、以下を導くことができる。 (= n1 (+ (* n2 (quotient n1 n2)) (remainder n1 n2))) => #t ただし演算に関係するすべての数は完全数とする。 (modulo 13 4) => 1 (remainder 13 4) => 1 (modulo -13 4) => 3 (remainder -13 4) => -1 (modulo 13 -4) => -3 (remainder 13 -4) => 1 (modulo -13 -4) => -1 (remainder -13 -4) => -1 (remainder -13 -4.0) => -1.0 ; 不完全数 [[ライブラリ手続き]] (gcd n1 ...) [[ライブラリ手続き]] (lcm n1 ...) 以上の手続きは、引数の最大公約数と最小公倍数を返す。結果は必ず非負の数である。 (gcd 32 -36) => 4 (gcd) => 0 (lcm 32 -36) => 288 (lcm 32.0 -36) => 288.0 ; 不完全数 (lcm) => 1 [[手続き]] (numerator q) [[手続き]] (denominator q) 以上の手続きは引数の分子もしくは分母を返す。結果は引数が規約分数であるかのように計算される。分母は常に正である。0の分母は1に定義される。 (numerator (/ 6 4)) => 3 (denominator (/ 6 4)) => 2 (denominator (exact->inexact (/ 6 4))) => 2.0 [[手続き]] (floor x) [[手続き]] (ceiling x) [[手続き]] (truncate x) [[手続き]] (round x) 以上の手続きは整数を返す。`floor'はxよりも大きくない最大の整数を返す。`celing'はxよりも小さくない最小の整数を返す。` truncate'は絶対値がxの絶対値よりも大きくない、xに最も近い整数を返す。`round'はxが二つの整数の中間にある場合でもそれを丸めて、xに最も近い整数を返す。 理論的根拠: `round'は、IEEE浮動小数点規格に指定されるデフォルトの 丸めモードと一貫性を保つように、数値を丸める。 注: 以上の手続きの引数が不完全数の場合は結果も不完全数である。完全数が必要な場合は、結果を`inexact->exact'手続きにかける必要がある。 (floor -4.3) => -5.0 (ceiling -4.3) => -4.0 (truncate -4.3) => -4.0 (round -4.3) => -4.0 (floor 3.5) => 3.0 (ceiling 3.5) => 4.0 (truncate 3.5) => 3.0 (round 3.5) => 4.0 ; 不完全数 (round 7/2) => 4 ; 完全数 (round 7) => 7 [[ライブラリ手続き]] (rationalize x y) `rationalize'は、y以上にはxと異ならない最も単純な有理数を返す。r1 = p1/q1かつr2 = p2/q2(規約分数)で、|p1| <= |p2|かつ|q1| <= |q2|ならば、有理数r1はもう一つの有理数r2よりも単純である。したがって3/5は4/7よりも単純である。すべての有理数がこの順にしたがうとは限らないが(2/7と3/5参照)、すべての区間には、その区間のその他すべての有理数よりも単純な有理数が一つ含まれる(2/7と3/5の間にはより単純な2/5が存在する)。0 = 0/1は、すべての有理数の中で最も単純であることに注意する必要がある。 (rationalize (inexact->exact .3) 1/10) => 1/3 ;完全数 (rationalize .3 1/10) => #i1/3 ;不完全数 [[手続き]] (exp z) [[手続き]] (log z) [[手続き]] (sin z) [[手続き]] (cos z) [[手続き]] (tan z) [[手続き]] (asin z) [[手続き]] (acos z) [[手続き]] (atan z) [[手続き]] (atan y x)) 以上の手続きは、実数全般をサポートするすべての処理系に実装され、通常の超越関数を計算する。`log'は、zの(常用対数ではなく)自然対数を計算する。`asin'、`acos'、`atan'はそれぞれ、arcsine(sin^-1)、acrcosine(cos^-1)、arctangent(tan^-1)を計算する。引数を二つ取る`atan'の別形は、複素数全般をサポートしない処理系においても、`(angle (make-rectangular x y))'(下記参照)を計算する。 一般に数学関数log、arcsine、arccosine、arctangentは、多重定義である。log(z)の値は、虚部が-pi(-piを除く)からpi(piを含む)の範囲にあるものとして定義される。log(0)は無定義である。logをこのように定義した場合、sin^-1(z)、cos^-1(z)、tan^-1(z)の値は次の式の通りとなる。 sin^-1(z) = -i*log(i*z + sqrt(1 - z^2)) cos^-1(z) = pi/2 - sin^-1(z) tan^-1(z) = (log(1 + i*z) - log(1 - i*z)) / (2*i) 以上の仕様は[CLTL]にしたがうものであり、[CLTL]はさらに[PENFIELD81]を引用している。分岐線法、境界条件、および上記関数の実装の詳細な検討については、原典にあたっていただきたい。上記手続きは、可能な時は実数引数から実数の結果を生成する。 [[手続き]] (sqrt z) zの主平方根を返す。結果は正の実部か、実部がゼロの非負の虚部になる。 [[手続き]] (expt z1 z2) z1のz2乗を返す。z1 =/= 0ならば、 z1^z2 = e^(z2*log(z1)) である。 0^zはz = 0ならば1、さもなければ0である。 [[手続き]] (make-rectangular x1 x2) [[手続き]] (make-polar x3 x4) [[手続き]] (real-part z) [[手続き]] (imag-part z) [[手続き]] (magnitude z) [[手続き]] (angle z) 以上の手続きは、複素数全般をサポートするすべての処理系に実装される。x1、x2、x3、x4が実数、zが複素数で次を満足するとすれば、 z = x1 + x2*i = x3 * e^(i*x4) (make-rectangular x1 x2) => z (make-polar x3 x4) => z (real-part z) => x1 (imag-part z) => x2 (magnitude z) => |x3| (angle z) => x_angle が返される。ただしある整数nに対してx_angle = x4 + 2*pi*nとして、-pi < x_angle <= piである。 理論的根拠: `magnitude'は実数引数に対しては`abs'と同じもの である。ただし`abs'はすべての処理系が実装しなければ ならないが、`magnitude'は複素数全般をサポートする 処理系にのみ実装される。 [[手続き]] (exact->inexact z) [[手続き]] (inexact->exact z) `exact->inexact'はzの*不完全*数表現を返す。返される値は数値的に引数に最も近い*不完全*数である。*完全数*引数にに近い適当な等価な*不完全*数が存在しない場合は、実装上の制限の侵害を報告することができる。 `inexact->exact'はzの*完全*数表現を返す。返される値は数値的に引数に最も近い*完全*数である。*不完全*数引数にに近い適当な等価な*完全*数が存在しない場合は、実装上の制限の侵害を報告することができる。 以上の手続きは、処理系に応じた全領域にわたって、*完全*整数と*不完全*整数の自然な一対一対応を実装するものである。*Note Implementation restrictions::参照。 ---------- Footnotes ---------- (1) transitive: 例えば関係`<'の場合で、x1string number) [[手続き]] (number->string number radix) radix(基数)は完全整数で、2、8、10、もしくは16でなければならない。省略した場合、基数はデフォルトの10に設定される。手続き`number->string'は数と基数の引数をそれぞれ一つづつ取って。その数とその基数による外部表現を、次の式が真となるような文字列として返す。 (let ((number number) (radix radix)) (eqv? number (string->number (number->string number radix) radix))) 上の式が真となる結果が存在しない場合はエラーである。 zが不完全数、基数が10で小数点を含む結果が上記の式を満足すれば、結果には小数点が含まれ、上記の式が真になる[HOWTOPRINT]、[HOWTOREAD]ために必要な最小の桁数を使用して結果が表現される(指数と後続する0を除く)。さもなければ結果の形式は不定である。 `number->string'が返す結果に明示的に基数接頭辞が含まれること はない。 注: エラー状況はzが複素数でないか、複素数であってもその実部か虚部が有理数でない場合にだけ、発生できる。 理論的根拠: zがflonumを使用して表現される不完全数で基数が10であれば、 結果に小数点を含めることによって上記の式は通常満足される。 無限大Nanと flonum表現については、結果を不定とする状況が 用意されている。 [[手続き]] (string->number string) [[手続き]] (string->number string radix) 渡された文字列が表す数を、最大精度の表現で返す。基数radixは2、8、10、16のいずれかの完全数でなければならない。基数が与えられた場合はそれがデフォルトの基数となり、これは文字列内の基数接頭辞(例えば"`#o177'")で明示的に上書きすることができる。基数が与えられていない場合のデフォルトの基数は10である。数について文字列が文法的に有効な記法でない場合は、` string->number'は#fを返す。 (string->number "100") => 100 (string->number "100" 16) => 256 (string->number "1e2") => 100.0 (string->number "15##") => 1500.0 注: 処理系は次のように、`string->number'の定義域を制限する場合がある。文字列に明示的な基数が含まれる時は、`string->number'は常に#fを返すことができる。サポートするすべての数が実数である処理系では、複素数の記法として文字列に極形式記法か矩形形式記法が使用された時は、`string->number'は常に#fを返すことができる。すべての数が整数の処理系では、記法に分数が使用された時は、`string->number'は常に#fを返すことができる。すべての数が完全数の処理系では、指数標識もしくは明示的な完全性接頭辞が使用された時、もしくは数字の代わりに#が書かれた場合でも、` string->number'は常に#fを返すことができる。すべての不完全数が整数の処理系では、小数点が使用された時は、`string->number'は常に#fを返すことができる。  File: r5rsj.info, Node: Other data types, Next: Control features, Prev: Numbers, Up: Standard procedures その他のデータ型 ================ * Menu: * Booleans:: * Pairs and lists:: * Symbols:: * Characters:: * Strings:: * Vectors:: 本節ではSchemeの数値以外のデータ型、すなわち論理型、ペア型、リスト型、シンボル型、文字型、文字列型、ベクタ型のあるものについての演算を説明する。  File: r5rsj.info, Node: Booleans, Next: Pairs and lists, Up: Other data types 論理式 ------ 真と偽に対する論理オブジェクトは#tと#fと書く。ただし実際に重要なものは、Schemeの条件式(`if'、`cond'、`and'、`or'、`do')が真または偽として処理するオブジェクトである。語句"真値"(単に"真"という場合もある)は、条件式が真として処理するあらゆるオブジェクトを意味する。語句"偽値"(単に"偽"という場合もある)は、条件式が偽として処理するあらゆるオブジェクトを意味する。 Schemeのすべての標準の値の内で、#fだけが条件式の中で偽と判断される。#fを除くSchemeのすべての標準の値は真と判断される。これには#t、ペア、空リスト、シンボル、数、文字列、ベクタ、手続きが含まれる。 注: Scheme以外のLisp方言に慣れているプログラマは、Schemeでは#fと空リストの両方とも、シンボル`nil'とは異なっていることに注意しなければならない。 論理定数はそれ自身に評価される。したがってプログラム内でクォートをつける必要はない。 #t => #t #f => #f '#f => #f [[ライブラリ手続き]] (not obj) `not'はobjが偽であれば#tを返し、それ以外では#f を返す。 (not #t) => #f (not 3) => #f (not (list 3)) => #f (not #f) => #t (not '()) => #f (not (list)) => #f (not 'nil) => #f [[ライブラリ手続き]] (boolean? obj) `boolean?'はobjが#tか#fのいずれかであれば#tを返し、それ以外の場合は#fを返す。 (boolean? #f) => #t (boolean? 0) => #f (boolean? '()) => #f  File: r5rsj.info, Node: Pairs and lists, Next: Symbols, Prev: Booleans, Up: Other data types ペアとリスト ------------ ペア(ドットペアと呼ばれることもある)は、car(カー)とcdr(クダー)と呼ばれる二つのフィールドを持つレコード構造である。carとcdrは歴史的にそう呼び慣わされている。ペアは`cons'手続きで作成される。carフィールドとcdrフィールドは、それぞれ手続き`car'と`cdr'で取り出される。carフィールドとcdrフィールドには、それぞれ手続き`set-car!'と`set-cdr!'で代入が行なわれる。 ペアは主としてリストを表現するのに使用される。リストは空リストであるか、cdrがリストであるペアとして再帰的に定義できる。さらに厳密にいえば、リストの集合は次のような最小の集合Xとして定義される。 * Xに空のリストが存在する。 * あるリストがXに含まれるとすれば、そのリストをcdrフィールドに含む いかなるリストもXに含まれる。 リストは連続するペアで構成され、各ペアのcarフィールドに含まれるオブジェクトがそのリストの要素である。例えば要素が二つのリストとは、リストの最初の要素であるcarとペアcdrで構成されるペアである。そのcdrは、carがリストの第2の要素であり、cdrのcdrが空のリストである。リストの長さは要素の数で、これはペアの数に等しい。 空のリストはこの型の中の特別のオブジェクトである(これはペアではない)。空のリストに要素はなく、その長さはゼロである。 注: 上記の定義は、リストがすべて有限の長さで、空のリストで終ることを意味している。 Schemeのペアのもっとも一般的な記法(外部表現)は"ドット付"記法(c1 . c2)である。ここにc1はcarフィールドの値、c2はcdrフィールドの値である。例えば`(4 . 5)'は、carが4でcdrが5のペアである。`(4 . 5)'はペアの外部表現であって、ペアに評価される式ではないことに注意しなければならない。 リストにはもっと簡素な記法が使用できる。リストの要素を単に空白で区切って小括弧で囲む。空のリストは()と書く。次に例を示す。 (a b c d e)と (a . (b . (c . (d . (e . ()))))) はシンボルのリストについての等価な記法である。最後が空のリストでない一連のペアは、変則リストと呼ばれる。変則リストはリストではないことに注意しなければならない。リストとドット記法を組み合わせて、変則リストを書くことができる。 (a b c . d)と (a . (b . (c . d))) とは等価である。 ペアがリストであるかどうかは、cdrフィールドに何が保管されているかによる。`set-cdr!'手続きを使用した時は、その瞬間リストであったものが次の瞬間にはリストでなくなる場合がある。 (define x (list 'a 'b 'c)) (define y x) y => (a b c) (list? y) => #t (set-cdr! x 4) => unspecified x => (a . 4) (eqv? x y) => #t y => (a . 4) (list? y) => #f (set-cdr! x x) => unspecified (list? x) => #f `read'手続きが読み込むリテラル式とオブジェクトの外部表現の内部では、'<データ>、`<データ>、`,'<データ>、`,@'<データ>は2要素リストを指す。その第一要素はそれぞれシンボル `quote'、`quasiquote'、`unquote'、`unquote-splicing'であり、いずれの場合もその第二要素は<データ>である。この規約は、任意のSchemeプログラムをリストで表現できるように用意したものである。Schemeの文法では、すべての<式>は<データ>でもある(*Note External representations (formal)::参照)。数ある特徴の中でもこれによって、`read'手続きを使用してSchemeプログラムを解析することができる。*Note External representations::参照。 [[手続き]] (pair? obj) `pair?'はobjがペアであれば#tを返し、それ以外の場合は#fを返す。 (pair? '(a . b)) => #t (pair? '(a b c)) => #t (pair? '()) => #f (pair? '#(a b)) => #f [[手続き]] (cons obj1 obj2) この手続きはペアを新しく割り当てて返し、そのcarはobj1、cdrはobj2である。このペアは、既存のすべてのオブジェクトとは(`eqv?'の意味で)異なることが保証されている。 (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 pair) この手続きはpairのcarフィールドの内容を返す。空リストの`car'を取った場合はエラーであることに注意しなければならない。 (car '(a b c)) => a (car '((a) b c d)) => (a) (car '(1 . 2)) => 1 (car '()) => error [[手続き]] (cdr pair) この手続きはpairのcdrフィールドの内容を返す。空リストの`cdr'を取った場合はエラーであることに注意しなければならない。 (cdr '((a) b c d)) => (b c d) (cdr '(1 . 2)) => 2 (cdr '()) => error [[手続き]] (set-car! pair obj) この手続きはpairのcarフィールドにobjを保管する。`set-car!'が返す値は不定である。 (define (f) (list 'not-a-constant-list))(1) (set-car! (f) 3) => unspecified (2) (set-car! (g) 3) => error (3) [[手続き]] (set-cdr! pair obj) この手続きはpairのcdrフィールドにobjを保管する。`set-cdr!'が返す値は不定である。 [[ライブラリ手続き]] (caar pair) [[ライブラリ手続き]] (cadr pair) ... ... [[ライブラリ手続き]] (cdddar pair) [[ライブラリ手続き]] (cddddr pair) 以上の手続きは`car'と`cdr'の組合せである。例えば`caddr'は次のように定義される。 (define caddr (lambda (x) (car (cdr (cdr x))))) 深さ4までの任意の組合せが用意されており、このような手続きは合計28ある。 [[ライブラリ手続き]] (null? obj) objが空リストの時に#tを返し、それ以外の場合は#fを返す。 [[ライブラリ手続き]] (list? obj) objがリストの場合は#tを返し、それ以外の場合は#fを返す。定義上すべてのリストは長さが有限で、終端は空リストである。 (list? '(a b c)) => #t (list? '()) => #t (list? '(a . b)) => #f (let ((x (list 'a))) (set-cdr! x x) (list? x)) => #f [[ライブラリ手続き]] (list obj ...) 引数を新しく割り当てたリストにして返す。 (list 'a (+ 3 4) 'c) => (a 7 c) (list) => () [[ライブラリ手続き]] (length list) リストlistの長さを返す。 (length '(a b c)) => 3 (length '(a (b) (c d e))) => 3 (length '()) => 0 [[ライブラリ手続き]] (append list ...) 最初のリストlistの要素にその他のリストの要素を続けたものを要素とするリストを返す。 (append '(x) '(y)) => (x y) (append '(a) '(b c d)) => (a b c d) (append '(a (b)) '((c))) => (a (b) (c)) 結果のリストは、最後のリスト引数と構造を共有する場合を除いて、必ず新しく割り当てられる。最後のリストは実際にはいかなるオブジェクトでもよい。最後のリストが正しいリストでない場合は、変則リストが生成される。 (append '(a b) '(c . d)) => (a b c . d) (append '() 'a) => a [[ライブラリ手続き]] (reverse list) listの要素を逆順にしたリストを新しく割り当てて返す。 (reverse '(a b c)) => (c b a) (reverse '(a (b c) d (e (f)))) => ((e (f)) d (b c) a) [[ライブラリ手続き]] (list-tail list k) listから最初のk個の要素を取り除いた部分リストを返す。listの要素数がk個より少い場合はエラーである。`list-tail'は次のように定義できる。 (define list-tail (lambda (x k) (if (zero? k) x (list-tail (cdr x) (- k 1))))) [[ライブラリ手続き]] (list-ref list k) listのk番目の要素を返す。(これは`(list-tail list k)'のcarに等しい)。listの要素数がk個より少かった場合はエラーである。 (list-ref '(a b c d) 2) => c (list-ref '(a b c d) (inexact->exact (round 1.8))) => c [[ライブラリ手続き]] (memq obj list) [[ライブラリ手続き]] (memv obj list) [[ライブラリ手続き]] (member obj list) 以上の手続きは、carがobjであるlistの部分リストを返す。ただしこの部分リストは、kがlistの長さ未満の場合に`(list-tail list k)'が返す空でないリストとする。objがlistに存在しなかった場合は、(空リストでなく)#fが返される。objとlistとの比較に`memq'は`eq?'を使用するが、`memv'は`eqv?'を、`member'は`equal?'を使用する。 (memq 'a '(a b c)) => (a b c) (memq 'b '(a b c)) => (b c) (memq 'a '(b c d)) => #f (memq (list 'a) '(b (a) c)) => #f (member (list 'a) '(b (a) c)) => ((a) c) (memq 101 '(100 101 102)) => unspecified (memv 101 '(100 101 102)) => (101 102) [[ライブラリ手続き]] (assq obj alist) [[ライブラリ手続き]] (assv obj alist) [[ライブラリ手続き]] (assoc obj alist) alist("association list" = 連想リスト)はペアのリストでなければならない。上記手続きはcarフィールドがobjである最初のペアを検索して、そのペアを返す。alistにcarがobjであるようなペアが存在しない場合は、(空リストではなく)#fが返される。各ペアのcarフィールドとobjとを比較するにあたって、`assq'は`eq?'を使用する。一方` assv'は`eqv?' を、`assoc'は`eequal?'を使用する。 (define e '((a 1) (b 2) (c 3))) (assq 'a e) => (a 1) (assq 'b e) => (b 2) (assq 'd e) => #f (assq (list 'a) '(((a)) ((b)) ((c)))) => #f (assoc (list 'a) '(((a)) ((b)) ((c)))) => ((a)) (assq 5 '((2 3) (5 7) (11 13))) => unspecified (assv 5 '((2 3) (5 7) (11 13))) => (5 7) 理論的根拠: `memq'、`memv'、`member'、`assq'、 `assv'、`assoc'は通常述語手続きとして使用される ものであるが、名前に疑問符が含まれていない。これらは単に #tか#fを返すのではなく、利用価値のある値を返すからである。 ---------- Footnotes ---------- (1) 訳注: この式は(define f (lambda () (list 'not-a-constant-list)))に等価である(*Note Definitions::参照)。すなわちfは、呼び出されるたびにリスト(not-a-constant-list)を生成して返す手続きである。(define (g) '(constant-list))は、(define g (lambda () '(constant-list)))に等価である。すなわちgは定数リスト(constant-list)を返す手続きである。 (2) 訳注: fが返すリストのcarに3を代入している。unspedifiedはset-car!が返す値である。 (3) 訳注: 返される定数リストのcarに3を代入している。定数の書き換えは通常はエラーである。素直に代入を許す処理系もある。  File: r5rsj.info, Node: Symbols, Next: Characters, Prev: Pairs and lists, Up: Other data types シンボル -------- シンボルは、二つのシンボルの名前と綴が同一の場合にのみ、(`eqv?'の意味で)その二つのシンボルが同一である点に利用価値があるオブジェクトである。これはプログラム内で識別子を表すのに必要な特徴である。したがってSchemeのほとんどの処理系では、その目的のために内部的にシンボルを使用している。シンボルはこれ以外の多くの応用にも利用価値が高い。例えばPascalで使用される列挙型の値のように使用することができる。 シンボルの表現規則は、識別子の表現規則と正確に等しい。*Note Identifiers::と*Note Lexical structure::参照。 リテラル式の一部として返されるか、もしくは`read'手続きを使用して読み込まれ、その後`write'手続きを使用して書き込まれたいかなるシンボルも、(`eqv?'の意味で)同一シンボルとしてもう一度読み込まれることが保証されている。ただし`string->symbol'手続きでは、`write/read'のこの不変性が維持されないシンボルが作成される場合がある。この手続きで標準以外の文字を使用して作成された名前には、特殊文字が含まれるからである。 注: Schemeの処理系によっては、すべてのシンボルに`write/read'の不変性を保証するために、"スラッシュ化"(slashification)(1)として知られる機能を備えているものがある。ただし歴史的にはこの機能の重要な利用法の大部分は、文字列データ型の不備を補うことであった。 処理系によっては"未登録のシンボル"(2)を使用するものがあり、これはスラッシュ化を使用する処理系においても`write/read'の不変性を破壊するものである。二つのシンボルの名前と綴が同一の場合にのみシンボルは等しいという規則にも例外が発生する。 [[手続き]] (symbol? obj) objがシンボルの場合に#tを返し、それ以外の場合は#fを返す。 (symbol? 'foo) => #t (symbol? (car '(a b))) => #t (symbol? "bar") => #f (symbol? 'nil) => #t (symbol? '()) => #f (symbol? #f) => #f [[手続き]] (symbol->string symbol) シンボルsymbolの名前を文字列として返す。シンボルがリテラル式(*Note Literal expressions::参照)の値として返されるオブジェクトの一部もしくは`read'手続きの呼び出しで返されるオブジェクトで、かつ名前にアルファベット文字が含まれる場合、この文字列には標準の文字が入る。標準の文字が大文字であるか小文字であるかは、処理系が決定する。処理系によって、小文字に統一される場合と大文字に統一される場合がある。シンボルが`string->symbol'によって返される場合は、`string->symbol'に渡される文字が大文字であれば大文字が、小文字であれば小文字が返される。この手続きが返す文字列に、`string-set!'などの変更手続きを使用した場合はエラーである。 以下の例は、処理系の標準文字が小文字であると仮定した場合である。 (symbol->string 'flying-fish) => "flying-fish" (symbol->string 'Martin) => "martin" (symbol->string (string->symbol "Malvina")) => "Malvina" [[手続き]] (string->symbol string) 名前が文字列stringであるシンボルを返す。この手続きは標準以外の文字集合の場合に名前に特殊文字が含まれるシンボルを作成できるが、そのようなシンボルを作成することは通常好ましい発想ではない。処理系によってはそのようなシンボルを読み込めないものがあるからである。`symbol->string'参照。 以下の例では標準文字が小文字であることを仮定している。 (eq? 'mISSISSIppi 'mississippi) => #t (string->symbol "mISSISSIppi") => the symbol with name "mISSISSIppi" (eq? 'bitBlt (string->symbol "bitBlt")) => #f (eq? 'JollyWog (string->symbol (symbol->string 'JollyWog))) => #t (string=? "K. Harper, M.D." (symbol->string (string->symbol "K. Harper, M.D."))) => #t ---------- Footnotes ---------- (1) リテラル性を確保したい部分をスラッシュなどで括る手法 (2) uninterned symbol  File: r5rsj.info, Node: Characters, Next: Strings, Prev: Symbols, Up: Other data types 文字型 ------ 文字型は、文字と数字などの印字文字を表すオブジェクトである。文字型は記法`#\<文字'もしくは`#\<文字名>'を使用して書かれる。例えば次の通りである。 #\a ; 小文字 #\A ; 大文字 #\( ; 左小括弧 #\ ; スペース #\space ; スペースを書く望ましい方法 #\newline ; newline文字 大文字と小文字の別は#\<文字>の場合は意味を持つが、#\<文字名>では意味を持たない。#\<文字名>内の<文字>がアルファベットの場合は、<文字>に続く文字列はスペースや括弧などの区切り文字でなければならない。この規則により例えば文字列"`#\space'"が、スペース文字を表すのか、それとも文字を表す"`#\s'"にシンボル"pace"が後続したものか、いずれにも解釈できるといった曖昧さが避けられる。 #\記法で書かれた文字はそれ自身に評価されるので、プログラム内でクォート(')をつける必要はない。 文字を扱う手続きの中には大文字と小文字を区別しないものがある。大文字と小文字を無視する手続きは、名称の中に"`-ci'"("case insensitive")が入っている。 [[手続き]] (char? obj) objが文字の場合には#tを返し、それ以外の場合には#fを返す。 [[手続き]] (char=? char1 char2) [[手続き]] (char? char1 char2) [[手続き]] (char<=? char1 char2) [[手続き]] (char>=? char1 char2) 以上の手続きのためには文字集合に関する完全な順序付けが必要である。順序づけが完全に行なわれていれば以下が保証される。 * 大文字には順序がある。例えば`(char? char1 char2) [[ライブラリ手続き]] (char-ci<=? char1 char2) [[ライブラリ手続き]] (char-ci>=? char1 char2) 以上の手続きは`char=?'その他に似ているが、大文字と小文字を同一のものとして処理するものである。例えば`(char-ci=? #\A #\a)'は#tを返す。処理系によっては手続きを一般化して、対応する数値述語手続きのように三つ以上の引数を取るようにしているものがある。 [[ライブラリ手続き]] (char-alphabetic? char) [[ライブラリ手続き]] (char-numeric? char) [[ライブラリ手続き]] (char-whitespace? char) [[ライブラリ手続き]] (char-upper-case? letter) [[ライブラリ手続き]] (char-lower-case? letter) 以上の手続きはそれぞれ、引数がアルファベット、数字、空白文字、大文字、小文字の場合に#tを返し、それ以外の場合は#fを返す。ASCII文字集合に固有の以下の注は、参考指針として述べるものである。アルファベット文字は大文字と小文字を合わせて52ある。数字は十進数で10ある。空白文字はスペース文字、タブ文字、改行文字、改ページ文字、キャリッジリターンである。 [[手続き]] (char->integer char) [[手続き]] (integer->char n) 文字を渡されると、`char->integer'はその文字の完全数による整数表現を返す。`char->integer'のもとでの文字イメージである完全整数を渡されると、`integer->char'は該当する文字を返す。以上の手続きは`char<=?'による順序づけのもとで文字集合間に、`<='による順序づけのもとで整数の部分集合の一部に、それぞれ順序を保存した同型写像(1)を実装するものである。すなわち (char<=? a b) => #t かつ (<= x y) => #t であり、かつxとyが`integer->char'の定義 域内にあれば、 (<= (char->integer a) (char->integer b)) => #t (char<=? (integer->char x) (integer->char y)) => #t である。 [[ライブラリ手続き]] (char-upcase char) [[ライブラリ手続き]] (char-downcase char) 以上の手続きは、`(char-ci=? char char2)'である文字char2を返す。さらにcharがアルファベット文字である場合は、`char-upcase'の結果は大文字、`char-downcase'の結果は小文字である。 ---------- Footnotes ---------- (1) order-preserving isomorphisms  File: r5rsj.info, Node: Strings, Next: Vectors, Prev: Characters, Up: Other data types 文字列 ------ 文字列は、文字が連続したものである。文字列は、文字の連続を二重引用符(`"')で括って書く。文字列内部の二重引用符は、エスケープ文字バックスラッシュ(`\')を使用した場合にのみ書くことができる。例えば次のようになる。 "The word \"recursion\" has many meanings." 文字列内部のバックスラッシュは、バックスラッシュをもう一つ使用してエスケープした場合にのみ書くことができる。文字列内部で二重引用符やバックスラッシュが後続しない単独のバックスラッシュの効果については、Schemeは指定していない。 文字列定数は二行に跨って連続することができるが、そのような文字列の正確な内容は不定である。 文字列の*長さ*は、その中に入っている文字の数である。この数は非負の整数で、文字列が作成された時に確定する。文字列の*有効な指標*は、文字列の長さ未満の非負の完全整数である。文字列の最初の文字の指標は0で始まり、二番目の文字の指標は1、以下同様である。 "指標startで始まり指標endで終る<文字列>"のような語句による表現をした場合は、指標startは指標に含まれ、指標endは指標に含まれない。したがってstartとendが同一の指標である場合は長さゼロの部分文字列が参照され、startがゼロでendが文字列の長さである場合は文字列全体が参照される。 文字列に作用する手続きの中には、大文字と小文字の違いを無視するものがある。大文字と小文字を無視する手続きの名前には"`-ci'"("case insensitive")が入る。 [[手続き]] (string? obj) objが文字列の場合に#tを返し、それ以外の場合は#fを返す。 [[手続き]] (make-string k) [[手続き]] (make-string k char) `make-string'は、長さkの文字列を新しく割り当てて返す。charが与えられた時は、文字列の要素がすべてそのcharで初期化される。それ以外の場合は文字列の内容は不定である。 [[ライブラリ手続き]] (string char ...) 引数で構成される文字列を新しく割り当てて返す。 [[手続き]] (string-length string) 渡された文字列stringの長さを返す。 [[手続き]] (string-ref string k) kは、有効な<文字列>指標でなければならない。`string-ref'は、開始値をゼロとする指標を使用して指標kの文字を返す。 [[手続き]] (string-set! string k char) kは有効な文字列指標でなければならない。`string-set!'は文字列stringの指標kの要素に文字charを格納して、不定の値を返す。 (define (f) (make-string 3 #\*)) (define (g) "***") (string-set! (f) 0 #\?) => unspecified (string-set! (g) 0 #\?) => error (string-set! (symbol->string 'immutable) 0 #\?) => error [[ライブラリ手続き]] (string=? string1 string2) [[ライブラリ手続き]] (string-ci=? string1 string2) 二つの文字列が同一の長さで、かつ同一の文字が同一の場所に入っている場合に#tを返す。それ以外の場合は#fを返す。`string-ci=?'は大文字と小文字を同一文字であるかのように処理するが、`string=?'では大文字と小文字が異なる文字として処理される。 [[ライブラリ手続き]] (string? string1 string2) [[ライブラリ手続き]] (string<=? string1 string2) [[ライブラリ手続き]] (string>=? string1 string2) [[ライブラリ手続き]] (string-ci? string1 string2) [[ライブラリ手続き]] (string-ci<=? string1 string2) [[ライブラリ手続き]] (string-ci>=? string1 string2) 以上の手続きは、文字の順序付手続きに対応して、手続きを辞書的な意味で文字列に拡張したものである。例えば`stringlist string) [[ライブラリ手続き]] (list->string list) `string->list'は、渡された文字列を構成する文字のリストを新しく割り当てて返す。`list->string'は、文字のリストlist(1)の文字で構成される文字列を、新しく割り当てて返す。`string->list'と`list->string'は、`equal?'の意味で逆関数である。 [[ライブラリ手続き]] (string-copy string) 渡された文字列stringのコピーを新しく割り当てて返す。 [[ライブラリ手続き]] (string-fill! string char) 渡された文字列stringのすべての要素にcharを格納する。返す値は不定である。 ---------- Footnotes ---------- (1) 例えば`(list->string '(#\a #\b #\c))'。  File: r5rsj.info, Node: Vectors, Prev: Strings, Up: Other data types ベクタ ------ ベクタは、整数で指標付を行なった要素で構成される、異成分からなる構造である。ベクタは通常同じ長さのリストよりも占有するメモリが少く、任意に選択した要素のアクセスに必要な平均時間も、通常はリストよりも少い。 ベクタの*長さ*は、ベクタに含まれる要素の数である。この数は非負の整数で、ベクタが作成された時に確定する。ベクタの*有効な指標*は、ベクタの長さよりも短い非負の完全整数である。ベクタの最初の要素には指標ゼロがつき、最後の要素にはベクタの長さよりも1少い指標がつく。 ベクタは、記法`\#(obj ...)'を使用して書かれる。例えば指標0の要素に数値ゼロ、指標1の要素にリスト`(2 2 2 2)'、指標2の要素に文字列`"Anna"'を含む長さ3のベクタは、次のように書く。 #(0 (2 2 2 2) "Anna") これがベクタの外部表現であって、ベクタに評価される式ではないことに注意する必要がある。リスト定数同様、ベクタ定数は次のようにクォートしなければならない(引用符をつける、もしくはquoteをつける)。 '#(0 (2 2 2 2) "Anna") => #(0 (2 2 2 2) "Anna") [[手続き]] (vector? obj) objがベクタの場合に#tを返し、それ以外の場合は#fを返す。 [[手続き]] (make-vector k) [[手続き]] (make-vector k fill) k個の要素を持つベクタを新しく割り当てて返す。二番目の引数が渡された場合は、要素の一つ一つがfillで初期化される。それ以外の場合は要素一つ一つの内容は不定である。 [[ライブラリ手続き]] (vector obj ...) 渡された引数を要素の内容とするベクタを、新しく割り当てて返す。`list'に相似の手続きである。 (vector 'a 'b 'c) => #(a b c) [[手続き]] (vector-length vector) ベクタvector内の要素数を完全整数で返す。 [[手続き]] (vector-ref vector k) kはベクタvectorの有効な指標でなければならない。`vector-ref'は、ベクタvectorの指標kの要素の内容を返す。 (vector-ref '#(1 1 2 3 5 8 13 21) 5) => 8 (vector-ref '#(1 1 2 3 5 8 13 21) (let ((i (round (* 2 (acos -1))))) (if (inexact? i) (inexact->exact i) i))) => 13 [[手続き]] (vector-set! vector k obj) kはベクタvectorの有効な指標でなければならない。`vector-set!'は、オブジェクトobjをベクタvectorの指標kの要素に格納する。`vector-set!'が返す値は不定である。 (let ((vec (vector 0 '(2 2 2 2) "Anna"))) (vector-set! vec 1 '("Sue" "Sue")) vec) => #(0 ("Sue" "Sue") "Anna") (vector-set! '#(0 1 2) 1 "doe") => error ; constant vector [[ライブラリ手続き]] (vector->list vector) [[ライブラリ手続き]] (list->vector list) `vector->list'は、ベクタvectorの要素に含まれるオブジェクトをリストにして、新しく割り当てて返す。`list->vector'はベクタを新に作成し、その要素をリストlistの要素に初期化して返す。 (vector->list '#(dah dah didah)) => (dah dah didah) (list->vector '(dididit dah)) => #(dididit dah) [[ライブラリ手続き]] (vector-fill! vector fill) ベクタvectorの一つ一つの要素すべてにfillを格納する。` vector-fill!'が返す値は不定である。