適切なシンプル型がなければ複合型(composite types)を使用することができます。複合型は特定のデータにより、他の型から新しい型を構築します。指定された型やデータは、その複合型の引数(argument)と呼ばれます。複合型は通常は以下のようなものです:
(constructor arguments...)
しかし以下のように引数の前にkeyword-valueペアーを追加することもできます。
(constructor {keyword value}... arguments...)
以下のテーブルに、コンストラクター(constructor)と複合型を記述するためにそれらを使用する方法を示します:
(cons car-type cdr-type)
値はコンスセルでなければならずCARはcar-type、CDRはcdr-typeに適合していなければならない。たとえば(cons
string symbol)
は、("foo" . foo)
のような値にマッチするデータ型となる。
カスタマイゼーションバッファーでは、CARとCDRはそれぞれ特定のデータ型に応じて個別に表示と編集が行われる。
(list element-types…)
値はelement-typesで与えられる要素と数が正確に一致するリストでなければならず、リストの各要素はそれぞれ対応するelement-typeに適合しなければならない。
たとえば(list integer string
function)
は3つの要素のリストを示し、1つ目の要素は整数、2つ目の要素は文字列、3つ目の要素は関数である。
カスタマイゼーションバッファーでは、各要素はそれぞれ特定のデータ型に応じて個別に表示と編集が行われる。
(group element-types…)
これはlist
と似ているが、Customバッファー内でのテキストのフォーマットが異なる。list
は各要素の値をそのタグでラベルづけするが、group
はそれを行わない。
(vector element-types…)
これはlist
と似ているが、リストではなくベクターでなければならない。各要素はlist
の場合と同様に機能する。
(alist :key-type key-type :value-type value-type)
値はコンスセルのリストでなければならず、各セルのCARはカスタマイゼーション型key-typeのキーを表し、同じセルのCDRはカスタマイゼーション型value-typeの値を表す。ユーザーはkey/valueペアーの追加や削除ができ、各ペアのキーと値の両方を編集することができる。
省略された場合のkey-typeとvalue-typeのデフォルトはsexp
。
ユーザーは指定されたkey-typeにマッチする任意のキーを追加できるが、:options
(カスタマイゼーション変数の定義を参照)で指定することにより、あるキーを優先的に扱うことができる。指定されたキーは、(適切な値とともに)常にカスタマイゼーションバッファーに表示される。またalistにkey/valueを含めるか、除外するか、それとも無効にするかを指定するチェックボックスも一緒に表示される。ユーザーは:options
キーワード引数で指定された値を変更できない。
:options
キーワードにたいする引数は、alist内の適切なキーにたいする仕様のリストであること。これらは通常は単純なアトムであり、それらは自身を意味します。たとえば:
:options '("foo" "bar" "baz")
これは名前が"foo"
、"bar"
、"baz"
であるような3つの既知のキーがあることを指定し、それらは常に最初に表示される。
たとえば"bar"
キーに対応する値を整数だけにするというように、特定のキーに対して値の型を制限したいときがあるかもしれない。これはリスト内でアトムのかわりにリストを使用することにより指定することができる。前述のように1つ目の要素はそのキー、2つ目の要素は値の型を指定する。たとえば:
:options '("foo" ("bar" integer) "baz")
最後にキーが表示される方法を変更したいときもあるだろう。デフォルトでは:options
キーワードで指定された特別なキーはユーザーが変更できないので、キーは単にconst
として表示される。しかしたとえばそれが関数バインディングをもつシンボルであることが既知なら、function-item
のようにあるキーの表示のためにより特化した型を使用したいと思うかもしれない。これはキーにたいしてシンボルを使うかわりに、カスタマイゼーション型指定を使用することにより行うことができる。
:options '("foo" ((function-item some-function) integer) "baz")
多くのalistはコンスセルのかわりに2要素のリストを使用する。たとえば、
(defcustom cons-alist '(("foo" . 1) ("bar" . 2) ("baz" . 3)) "Each element is a cons-cell (KEY . VALUE).")
のかわりに以下を使用する
(defcustom list-alist '(("foo" 1) ("bar" 2) ("baz" 3)) "Each element is a list of the form (KEY VALUE).")
リストはコンスセルの最上位に実装されているため、上記のlist-alist
をコンスセルのalist(値の型が実際の値を含む1要素のリスト)として扱うことができる。
(defcustom list-alist '(("foo" 1) ("bar" 2) ("baz" 3)) "Each element is a list of the form (KEY VALUE)." :type '(alist :value-type (group integer)))
list
のかわりにgroup
を使用するのは、それが目的に適したフォーマットだという理由だけである。
同様に以下のようなトリックの類を用いることにより、より多くの値が各キー連づけられたalistを得ることができる:
(defcustom person-data '(("brian" 50 t) ("dorith" 55 nil) ("ken" 52 t)) "Alist of basic info about people. Each element has the form (NAME AGE MALE-FLAG)." :type '(alist :value-type (group integer boolean)))
(plist :key-type key-type :value-type value-type)
このカスタマイゼーション型はalist
(上記参照)と似ているが、(1)情報がプロパティリスト(プロパティリストを参照)に格納されていて、(2)key-typeが省略された場合のデフォルトはsexp
ではなくsymbol
になる。
(choice alternative-types…)
値はalternative-typesのうちのいずれかに適合しなければならない。たとえば(choice integer
string)
では整数か文字列が許容される。
カスタマイゼーションバッファーでは、ユーザーはメニューを使用して候補を選択して、それらの候補にたいして通常の方法で値を編集できる。
通常はこの選択からメニューの文字列が自動的に決定される。しかし候補の中に:tag
キーワードを含めることにより、メニューにたいして異なる文字列を指定できる。たとえば空白の数を意味する整数と、その通りに使用したいテキストにたいする文字列なら、以下のような方法でカスタマイゼーション型を記述したいと思うかもしれない
(choice (integer :tag "Number of spaces") (string :tag "Literal text"))
この場合のメニューは‘Number of spaces’と‘Literal text’を提示する。
const
以外のnil
が有効な値ではない選択肢には、:value
キーワードを使用して有効なデフォルト値を指定すること。型キーワードを参照のこと。
複数の候補によりいくつかの値が提供されるなら、カスタマイズは適合する値をもつ最初の候補を選択する。これは常にもっとも特有な型が最初で、もっとも一般的な型が最後にリストされるべきことを意味する。以下は適切な使い方の例である
(choice (const :tag "Off" nil) symbol (sexp :tag "Other"))
この使い方では特別な値nil
はその他のシンボルとは別に扱われ、シンボルは他のLisp式とは別に扱われる。
(radio element-types…)
¶これはchoice
と似ているが、選択はメニューではなくラジオボタンで表示される。これは該当する選択にたいしてドキュメントを表示できる利点があるので、関数定数(function-item
カスタマイゼーション型)の選択に適している場合がある。
(const value)
値はvalueでなければならず他は許容されない。
const
は主にchoice
の中で使用される。たとえば(choice integer (const
nil))
では整数かnil
が選択できる。
choice
の中では:tag
とともにconst
が使用される場合がある。たとえば、
(choice (const :tag "Yes" t) (const :tag "No" nil) (const :tag "Ask" foo))
これはt
がyes、nil
がno、foo
が“ask”を意味することを示す。
(other value)
この選択肢は任意のLisp値にマッチできるが、ユーザーがこの選択肢を選択したら値valueが選択される。
other
は主にchoice
の最後の要素に使用される。たとえば、
(choice (const :tag "Yes" t) (const :tag "No" nil) (other :tag "Ask" foo))
これはt
がyes、nil
がno、それ以外は“ask”を意味することを示す。ユーザーが選択肢メニューから‘Ask’を選択したら、値foo
が指定される。しかしその他の値(t
、nil
、foo
を除く)ならfoo
と同様に‘Ask’が表示される。
(function-item function)
const
と同様だが値が関数のときに使用される。これはドキュメント文字列も関数名と同じように表示する。ドキュメント文字列は:doc
で指定した文字列かfunction自身のドキュメント文字列。
(variable-item variable)
const
と同様だが値が変数名のときに使用される。これはドキュメント文字列も変数名と同じように表示する。ドキュメント文字列は:doc
で指定した文字列かvariable自身のドキュメント文字列。
(set types…)
値はリストでなければならず指定されたtypesのいずれかにマッチしなければならない。
これはカスタマイゼーションバッファーではチェックリストとして表示されるので、typesはそれぞれ対応する要素を1つ、あるいは要素をもたない。同じ1つのtypesにマッチするような、異なる2つの要素を指定することはできない。たとえば(set
integer
symbol)
はリスト内で1つの整数、および/または1つのシンボルが許容されて、複数の整数や複数のシンボルは許容されない。結果としてset
内でinteger
のような特化していない型を使用するのは稀である。
以下のようにconst
型はset
内のtypesでよく使用される:
(set (const :bold) (const :italic))
alist内で利用できる要素を示すために使用されることもある:
(set (cons :tag "Height" (const height) integer) (cons :tag "Width" (const width) integer))
これによりユーザーにオプションでheightとwidthの値を指定させることができる。
(repeat element-type)
値はリストでなければならず、リストの各要素は型element-typeに適合しなければならない。カスタマイゼーションバッファーでは要素のリストとして表示され、‘[INS]’と‘[DEL]’ボタンで要素の追加や削除が行われる。
(restricted-sexp :match-alternatives criteria)
¶これはもっとも汎用的な複合型の構築方法である。値はcriteriaを満足する任意のLispオブジェクト。criteriaはリストで、リストの各要素は以下のうちのいずれかを満たす必要がある:
nil
か非nil
のどちらかをリターンする関数。リスト内での述語の使用により、その述語が非nil
をリターンするようなオブジェクトが許されることを意味する。
'object
。リスト内でこの要素はobject自身が許容される値であることを示す。
たとえば、
(restricted-sexp :match-alternatives (integerp 't 'nil))
これは整数、t
、nil
を正当な値として受け入れる。
カスタマイゼーションバッファーは適切な値をそれらの入力構文de表示して、ユーザーはこれらをテキストとして編集できる。
以下は複合型でキーワード/値ペアーとして使用できるキーワードのテーブルです:
:tag tag
tagはユーザーとのコミュニケーションのために、その候補の名前として使用される。choice
内に出現する型にたいして有用。
:match-alternatives criteria
¶criteriaは可能な値とのマッチに使用される。restricted-sexp
内でのみ有用。
:args argument-list
¶型構築の引数としてargument-listの要素を使用する。たとえば(const :args
(foo))
は(const
foo)
と等価である。明示的に:args
と記述する必要があるのは稀である。なぜなら最後のキーワード/値ペアーの後に続くものは何であれ、引数として認識されるからである。