Gauche:find系APIの整理
Shiro(2021/05/28 21:55:42 UTC): 「コレクションから条件に合う要素を見つける」という操作について、命名やインタフェースに若干混乱があるので整理
find系
pred :: element -> generalized-boolean- 最初にtruthを返した
elementを返す - 辞書系のコレクションの場合、predはkeyとvalueを取る。見つかった場合には2値を返す。
- APIについては以下のバリエーション
:: pred, collection -> element: 元祖find。みつからなかったら#fを返す。欠点として、見つけたい要素が#fである場合を扱えない。findsrfi-1, scheme.list ifindsrfi-116, scheme.ilist generator-findsrfi-158, scheme.generator lseq-findsrfi-127, scheme.lseq stream-findutil.stream (Gauche独自) :: pred, collection, (() -> element) -> element: 見つからなかった時に呼び出すfailure thunkを取るもの。新しめのsrfiに多い。bag-findsrfi-113, scheme.set hashmap-findsrfi-146, scheme.mapping idequeue-findsrfi-134, scheme.idequeue (failureはoptional) iset-findsrfi-217 mapping-findsrfi-146, scheme.mapping set-findsrfi-113, scheme.set :: collection, pred, :optional (() -> element) -> element: 述語とコレクションの順序が逆。これはGauche specificな次の手続きだけなので、0.9.11で上の2.に揃える。binary-heap-find**data.heap :: collection, pred -> key, value, found?:hashtable-findsrfi-126
hash-table-find(Gauche, srfi-125)は下のany系になる。
汎用性を考えるなら「pred, collection, :optional failure -> element」で統一するのが良さそう。3.は歴史的遺物だけど、互換性を残したまま引数は入れ替えられるので、2.に統一すべき。
collectionが順序つきの場合、「逆方向から探す」というバリエーションがあり得る。
:: pred, collection -> elementifind-tailsrfi-116, scheme.ilist lseq-find-tailsrfi-127, scheme.lseq stream-find-tailutil.stream, Gauche独自 :: pred, collection, (() -> element) -> elementidequeue-find-rightsrfi-134, scheme.idequeue (failureはoptional)
any系
pred :: element -> result- 最初にpredがtruthを返した時の返り値をそのまま返す (要素の値ではなく)
- APIのバリエーション
:: pred, collection -> result: 見つからなかった場合は#f。char-set-anysrfi-14, scheme.charset generator-anysrfi-158, scheme.genrator lseq-anysrfi-127, scheme.lseq :: pred, collection, ... -> result: collectionを複数取る。見つからなかった場合は#f。anysrfi-1, scheme.list array-anysrfi-179 flexvector-anysrfi-214 ianysrfi-116, scheme.ilist idequeue-anysrfi-134, scheme.idequeue range-anysrfi-196 stream-anyutil.stream, Gauche独自 vector-anysrfi-133, scheme.vector @vector-anysrfi-160, scheme.vector.@ :: pred, collection, :optional (() -> result) -> result: failure thunkを取るhash-table-findsrfi-125, scheme.hash-table :: collection, pred, :optional (() -> result) -> result: 2.のpredとcollectionが逆。これはGauche組み込みで後方互換性のため。だがhash-table-findGauche :: pred, collection, :optional start end -> result: 見つからなかったら#f。string-anysrfi-13 textual-anysrfi-135, scheme.text
any? 系
pred :: element -> generalized-boolean- predがtruthを返したら直ちに
#tを、そうでなければ#fを返す。「見つかったものは何か」に関する情報は返せない。 - APIのバリエーション
:: pred, collection -> booleanbag-any?srfi-113, scheme.set enum-set-any?srfi-209 hashmap-any?srfi-146, scheme.mapping iset-any?srfi-217 mapping-any?srfi-146, scheme.mapping set-any?srfi-113, scheme.set :: collection, start, end -> boolean: ビットを扱うもの。predは自明なので取らない。bit-field-any?srfi-151, scheme.bitwise bitvector-field-any?srfi-178
seek系
find、any、またいくつかのsrfiにみられるsearch系(predicateではなく探す要素を取り、結果に応じて呼ばれる継続手続きを取る)を統一的に実装するために、
Gaucheでgauche.dictionaryに実験的に入れてみたもの。まだundocumented。
- 0.9.10時点では以下のシグネチャ
*-seek :: collection, pred, success, failurepred :: element -> resultsuccess :: result, key, value -> *failure :: () -> *
dictionary frameworkで使うなら、collectionが先に来る方が良い。
継続手続きに関しては、search系がfailure, successの順なのでそれに合わせる方が良いか。0.9.11で変える。
Maybeモナド
- まだ実装はないが、srfi-189のmaybeを使うことで、見つからなかった場合と見つかった時に返す値を明確に区別できる
- find系とany系が考えられる。
Maybe find系
:: (element -> generalized-boolean), collection -> Maybe element
Maybe any系
:: (element -> Maybe result), collection -> Maybe result