I am having trouble understanding the use of collector functions in Scheme. I am using the book "The Little Schemer" (by Daniel P. Friedman and Matthias Felleisen). A comprehensive example with some explanation would help me massively. An example of a function using a collector function is the following snippet:
(define identity
(lambda (l col)
(cond
((null? l) (col '()))
(else (identity
(cdr l)
(lambda (newl)
(col (cons (car l) newl))))))))
... with an example call being (identity '(a b c) self) and the self-function being (define self (lambda (x) x)). The identity function returns the given list l, so the output of the given call would be (a b c). The exact language used is the R5RS Legacy-language.
Given how those "collector" functions are defined in the
identitydefinition, callingfor any list
xsand some "collector" functioncol, is equivalent to callingso the same list will be "returned" i.e. passed to its argument "collector" / continuation function
col. That explains its name,identity, then.For comparison, a
reversecould be coded asThis style of programming is known as continuation-passing style: each function is passed a "continuation" that is assumed that it will be passed the result of the rest of computation, so that the original continuation / collector function will be passed the final result eventually. Each collector's argument represents the future "result" it will receive, and the collector function itself then specifies how it is to be handled then.
Don't get confused by the terminology: these functions are not "continuations" captured by the
call/ccfunction, they are normal Scheme functions, representing "what's to be done next".The definition can be read as
(or we can write this in a pseudocode, as)
col2handles its argumentrby passing(cons x r)to the previous handlercol. This meansris transformed into(cons x r), but instead of being returned as a value, it is fed intocolfor further processing. Thus we "return" the new value(cons x r)by passing it to the previous "collector".A sample call, as an illustration:
update: in a pattern-matching pseudocode I've been fond of using as of late, we could write
and
which hopefully is so much visually apparent that it almost needs no explanation!