R6RS:翻訳:Standard Libraries:14 Enumerations
14 章 列挙
本章では列挙値と列挙値の集合を扱う (rnrs enums (6)) ライブラリについて述べる。列挙値はふつうのシンボルで表現される一方で、列挙値の有限集合は別個の型であり、これは列挙集合と呼ばれる。列挙集合はさらに同一の母集団と列挙型を共有する列挙集合群に分割される。この母集団と列挙型はは make-enumeration 手続きで作成される。この手続きへの呼び出しは毎回新たな列挙型を作成する。
本ライブラリではそれぞれの列挙集合をシンボルの特定の母集団と列挙型で解釈する。これにより、列挙集合を効率的に実装することがけいるようになり、補集合演算が行なえるようになる。
以下の手続きの説明で enum-set は列挙集合にわたり、 make-enumeration で定義された母集団の部分集合として定義される。
[procedure] (make-enumeration symbol-list)
symbol-list はシンボルのリストでなければならない。 make-enumeration 手続きは母集団がそのシンボル群(順番はリストに最初に現れた順である)である列挙型であり、その母集団が母集団自体であり列挙型が新たに作られた列挙型である母集団を返す。
[procedure] (enum-set-universe enum-set)
引き数の母集団を包含するシンボルの集合を列挙集合として返す。
[procedure] (enum-set-indexer enum-set)
enum-set の母集団にあるシンボルを受け取り、母集団中での 0 から始まる順番を返す 1 引き数の手続きを返す。与えられた値が母集団にない場合には、手続きは #f を返す。
(let* ((e (make-enumeration ’(red green blue))) (i (enum-set-indexer e))) (list (i ’red) (i ’green) (i ’blue) (i ’yellow))) ⇒ (0 1 2 #f)
enum-set-indexer 手続きは (rnrs lists (6)) ライブラリの memq 手続きを使って次のように定義することができる。
(define (enum-set-indexer set) (let* ((symbols (enum-set->list (enum-set-universe set))) (cardinality (length symbols))) (lambda (x) (cond ((memq x symbols) => (lambda (probe) (- cardinality (length probe)))) (else #f)))))
[procedure] (enum-set-constructor enum-set)
enum-set の母集団に属するシンボルのリストを受け取り、母集団の部分集合で、そのリストに含まれるシンボルのリストだけを返す 1 引き数の手続きを返す。リスト中の値はすべて母集団に属していなければならない。
[procedure] (enum-set->list enum-set)
引き数に属するシンボルのリストを、 enum-set の母集団の正規化された順序で返す。
(let* ((e (make-enumeration ’(red green blue))) (c (enum-set-constructor e))) (enum-set->list (c ’(blue red)))) ⇒ (red blue)
[procedure] (enum-set-member? symbol enum-set)
[procedure] (enum-set-subset? enum-set1 enum-set2)
[procedure] (enum-set=? enum-set1 enum-set2)
enum-set-member 手続きは最初の引き数が 2 番目の引き数の要素である場合 #t を返し、そうでない場合 #f を返す。
enum-set-subset? 手続きは(シンボルの集合として考えたとき) enum-set1 の母集団が enum-set2 の母集団の部分集合であり、 enum-set1 の要素がすべて enum-set2 の要素である場合 #t を返す。それ以外の場合は #f を返す。
enum-set=? 手続きは、 enum-set-subset? 手続きで決定されるところで、 enum-set1 が enum-set2 の部分集合でかつ逆もまた真の場合に #t を返す。これはふたつの集合の母集団がシンボルの集合として等しいことを言っているが、列挙型として等しいことは言っていない。この条件を満たさない場合には #f が返る。
(let* ((e (make-enumeration ’(red green blue))) (c (enum-set-constructor e))) (list (enum-set-member? ’blue (c ’(red blue))) (enum-set-member? ’green (c ’(red blue))) (enum-set-subset? (c ’(red blue)) e) (enum-set-subset? (c ’(red blue)) (c ’(blue red))) (enum-set-subset? (c ’(red blue)) (c ’(red))) (enum-set=? (c ’(red blue)) (c ’(blue red))))) ⇒ (#t #f #t #t #f #t)
[procedure] (enum-set-union enum-set1 enum-set2)
[procedure] (enum-set-intersection enum-set1 enum-set2)
[procedure] (enum-set-difference enum-set1 enum-set2)
enum-set1 と enum-set2 は同一の列挙型の列挙集合でなければならない。
enum-set-union 手続きは enum-set1 と enum-set2 の和集合を返す。 enum-set-interection 手続きは共通部分を返し、 enum-set-difference 手続きは集合の差を返す。
(let* ((e (make-enumeration ’(red green blue))) (c (enum-set-constructor e))) (list (enum-set->list (enum-set-union (c ’(blue)) (c ’(red)))) (enum-set->list (enum-set-intersection (c ’(red green)) (c ’(red blue)))) (enum-set->list (enum-set-difference (c ’(red green)) (c ’(red blue)))))) ⇒ ((red blue) (red) (green))
[procedure] (enum-set-complement enum-set)
enum-set の母集団における補集合を返す。
(let* ((e (make-enumeration ’(red green blue))) (c (enum-set-constructor e))) (enum-set->list (enum-set-complement (c ’(red))))) ⇒ (green blue)
[procedure] (enum-set-projection enum-set1 enum-set2)
enum-set1 を enum-set2 の母集団に写像する。このとき、 enum-set2 の母集団に属さない enum-set1 の要素は除外される(enum-set1 が 2 番目のものの部分集合であった場合、どの要素も除外されず、単射が返る)。
(let ((e1 (make-enumeration ’(red green blue black))) (e2 (make-enumeration ’(red black white)))) (enum-set->list (enum-set-projection e1 e2)))) ⇒ (red black)
[syntax] (define-enumeration <type-name> (<symbol> ...) <constructor-syntax>)
define-enumeration フォームは列挙型を定義し、その要素と要素の集合を構築するマクロをふたつ提供する。
define-enumeration フォームは定義であり、他の <definition> の現れられる場所にはどこにでも現れることができる。
<type-name> は識別子で、構文キーワードに束縛される。 <symbol> ... はシンボルで列挙の包含する母集団を(順番に)並べたものである。
(<type-name> <symbol>) はマクロ展開時にシンボルの名前が <type-name> に関連づけられた母集団に属しているかを検する。そうであれば、 (<type-name> <symbol>) は <symbol> と等価である。そうでなければ構文違反である。
<constructor-syntax> は識別子で母集団中のシンボルの有限の列を重複を許し与え、それらのシンボルの列挙集合に評価される式に展開されるマクロに束縛される。
(<construct-syntax> <symbol> ...) はマクロ展開時に各 <symbol> ... が <type-name> に対応する母集団に含まれるかを検する。ひとつ以上がこれを満たさない場合は構文違反である。それ以外の場合は
(<constructor-syntax> <symbol> ...)
は
((enum-set-constructor (<constructor-syntax>)) ’(<symbol> ...))
と等価である。
例:
(define-enumeration color (black white purple maroon) color-set) (color black) ⇒ black (color purpel) ⇒ &syntax exception (enum-set->list (color-set)) ⇒ () (enum-set->list (color-set maroon white)) ⇒ (white maroon)
注: (<type-name> <symbol>) と (<constructor-syntax> <symbol> ...) フォームでは <symbol> の名前にだけ意味がある。