これらの「コレクター」関数が定義でどのように定義されているかを考えるとidentity
、呼び出し
(identity xs col)
任意のリストxs
といくつかの「コレクター」関数col
に対して、呼び出しと同等です
(col xs)
したがって、同じリストが「返され」ます。つまり、その引数「コレクター」/継続関数に渡されますcol
。それはその名前を説明していますidentity
、それでは。
比較のために、aは次のreverse
ようにコーディングできます。
(define reverse ; to be called as e.g. (reverse l display)
(lambda (l col)
(cond
((null? l) (col '())) ; a reversed empty list is empty
(else (reverse (cdr l) ; a reversed (cdr l) is newl --
(lambda (newl) ; what shall I do with it when it's ready?
(col ; append (car l) at its end and let col
(append newl ; deal with it!
(list (car l))))))))))
このスタイルのプログラミングは、継続渡しスタイルとして知られています。各関数には、残りの計算の結果が渡されると想定される「継続」が渡されるため、元の継続/コレクター関数に最終結果が渡されます。最終的。各コレクターの引数は、それが受け取る将来の「結果」を表し、コレクター関数自体がそれをどのように処理するかを指定します。
用語に惑わされないでください: これらの関数は、関数によってキャプチャされた「継続」ではなくcall/cc
、通常の Scheme 関数であり、「次に行われること」を表します。
定義は次のように読むことができます。
identity :
to transform a list xs
with a collector function col,
is
| to call (col xs) , if xs is empty, or
| to transform (cdr xs)
with a new collector function col2
such that
(col2 r) = (col (cons (car xs) r)) , otherwise.
(または、これを疑似コードで次のように記述できます)
(identity list col) =
| empty? list -> (col list)
| match? list (x . xs) -> (identity xs col2)
where
(col2 r) = (col (cons x r))
col2
前の handler に r
渡すことによって、その引数を処理します。この手段は に変換されますが、値として返される代わりに、さらに処理するために に渡されます。したがって、新しい値を前の「コレクター」に渡すことで、新しい値を「返します」。(cons x r)
col
r
(cons x r)
col
(cons x r)
例としての呼び出しの例:
(identity (list 1 2 3) display)
= (identity (list 2 3) k1)
; k1 = (lambda (r1) (display (cons 1 r1))) = display ° {cons 1}
= (identity (list 3) k2)
; k2 = (lambda (r2) (k1 (cons 2 r2))) = k1 ° {cons 2}
= (identity (list ) k3)
; k3 = (lambda (r3) (k2 (cons 3 r3))) = k2 ° {cons 3}
= (k3 '()) ; (((display ° {cons 1}) ° {cons 2}) ° {cons 3}) []
= (k2 (cons 3 '())) ; ((display ° {cons 1}) ° {cons 2}) [3]
= (k1 (cons 2 (list 3))) ; (display ° {cons 1}) [2,3]
= (display (cons 1 (list 2 3))) ; display [1,2,3]
= (display (list 1 2 3))
更新:最近私が好んで使用しているパターン マッチングの疑似コードでは、次のように記述できます。
identity [] col = col []
identity [a, ...d] col = identity d ( newl => col [a, ...newl] )
と
reverse [] col = col []
reverse [a, ...d] col = reverse d ( newl => col [...newl, a] )
うまくいけば、視覚的に非常に明白であり、ほとんど説明する必要はありません!