[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.14 srfi-42 - 先行評価的内包表記

Module: srfi-42

このモジュールはジェネリックな内包表記(comprehension)機構を提供します。 この機構は他の言語(Haskell、Pythonなど)では組み込みの機構になっていま す。この機構は豊富な操作手続を提供しているので、リストジェネレータとい うだけではなく、ジェネリックなループ構文(Common Lisp の loop マ クロ並みに強力/邪悪だという人もいます)を提供しています。

この機構は先行評価的に走ります。すなわち、リストを生成する場合、評価時 にすべてのリストを生成します。要素を要求駆動的に生成するわけで はありません。それゆえ、無限列を表現することはできません。それが自然に できる Haskell とは違います。Schemeにおいては無限列を扱うのなら遅延評 価をするように構築されたストリームが使えます。

先行評価的内包表記の例

いくつかの例からはじめましょう。

5番目までの整数の自乗のリストを生成しましょう。

 
(list-ec (: i 5) (* i i)) ⇒ (0 1 4 9 16)

数の対(x y)の集合を生成します。ここでxは 2以上 5未満、yは1以上 x 未満です。

 
(list-ec (: x 2 5) (: y 1 x) (list x y))
  ⇒ ((2 1) (3 1) (3 2) (4 1) (4 2) (4 3))

上の2つの例はHaskellで書くと以下のようになります。

 
[ i*i   | i <- [0..4] ]
[ (x,y) | x <- [2..4], y <- [1..x-1] ]

違いに注意:(1) Haskellでは要素になる本体部が先にきて、そのあとに修飾 部(セレクタ)がきます。SRFI-42では本体部は最後になります。(2) SRFI-42で は範囲指定の下限はそれを含み、上限はそれを含みません。

a^3+b^3 = c^3+d^3を満すような数字の集合(a b c d)を列挙し ましょう。

 
(define (taxi-number n)
  (list-ec (: a 1 n)
           (: b (+ a 1) n)
           (: c (+ a 1) b)
           (: d (+ c 1) b)
           (if (= (+ (expt a 3) (expt b 3))
                  (+ (expt c 3) (expt d 3))))
           (list a b c d)))

リストだけではなく、他のシーケンスも生成できます。

 
(vector-ec (: i 5) i) ⇒ #(0 1 2 3 4)
(string-ec (: i 5) (integer->char (+ i 65))) ⇒ "ABCDE"

畳み込み演算も適用できます。

 
(sum-ec (: i 1 100) i)
  ⇒ 4950    ;; 1以上100未満の整数の和
(product-ec (: i 1 10) i)
  ⇒ 362880 ;;  1以上10未満の整数の積

内包表記マクロ

それぞれの内包表記は以下のような形式になります。

 
(comprehension-macro qualifierbody)

qualifierごとにbodyをくりかえし評価します。内包表記の種類 によって、bodyの結果は(リスト、ベクタ、文字列などに)集約されるか、 (sum、product、min、maxなどによって)畳み込まれるか、あるいは、単に捨て られます。

いくつかの内包表記では、追加の値がqualifiersの前か、bodies の後に置かれます。

Macro: do-ec qualifier … body

[SRFI-42]

Macro: list-ec qualifier … body

[SRFI-42]

Macro: append-ec qualifier … body

[SRFI-42]

Macro: string-ec qualifier … body
Macro: string-append-ec qualifier … body

[SRFI-42]

Macro: vector-ec qualifier … body

[SRFI-42]

Macro: vector-of-length-ec qualifier … body

[SRFI-42]

Macro: sum-ec qualifier … body
Macro: product-ec qualifier … body
Macro: min-ec qualifier … body
Macro: max-ec qualifier … body

[SRFI-42]

Macro: any?-ec qualifier … test
Macro: every?-ec qualifier … test

[SRFI-42]

Macro: first-ec default qualifier … body
Macro: last-ec default qualifier … body

[SRFI-42]

Macro: fold-ec x0 qualifier … expr f2
Macro: fold3-ec x0 qualifier … expr f1 f2

[SRFI-42]

Qualifiers

Control qualifiers

EC Qualifier: if test
EC Qualifier: not test
EC Qualifier: and test
EC Qualifier: or test
EC Qualifier: begin test
EC Qualifier: nested test

Generational qualifiers

EC Qualifier: : vars arg1 args …
EC Qualifier: :list vars arg1 args …
EC Qualifier: :vector vars arg1 args …
EC Qualifier: :string vars arg1 args …
EC Qualifier: :integers vars
EC Qualifier: :range vars stop
EC Qualifier: :range vars start stop
EC Qualifier: :range vars start stop step
EC Qualifier: :real-range vars stop
EC Qualifier: :real-range vars start stop
EC Qualifier: :real-range vars start stop step
EC Qualifier: :char-range vars min max
EC Qualifier: :port vars port
EC Qualifier: :port vars port read-proc
EC Qualifier: :dispatched vars dispatch arg1 args …
EC Qualifier: :do (lb …) ne1? (ls …)
EC Qualifier: :do (let (ob …) oc …) (lb …) ne1? (let (ib …) ic …) ne2? (ls …)
EC Qualifier: :let vars expr
EC Qualifier: :parallel generator …
EC Qualifier: :while generator expr
EC Qualifier: :until generator expr

[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on October, 7 2008 using texi2html 1.78.