Am Do., 21. Feb. 2019 um 10:38 Uhr schrieb Marc Nieper-Wißkirchen <xxxxxx@gmail.com>:
>
> Am Do., 21. Feb. 2019 um 10:17 Uhr schrieb Alex Shinn <xxxxxx@gmail.com>:
[...]
> > Mostly to have and compare the alternate implementation strategy,
> > and I suspect it may be less hairy.
>
> I will let you know when I will have found the time to implement (show
> columnar).
In (chibi show columnar) first-class continuations are only used in "call-with-output-generator". The reason why first-class continuations are used there is the same, why "make-coroutine-generator" of SRFI 121 depends on first-class continuation. Therefore, it may be a good idea, not to use first-class continuations in (chibi show columnar) but to let the (lower level) SRFI 121 do all the dirty work (which may or may not be implemented with first-class continuations).
And indeed it works out quite elegantly!
First of all, let us define the following monadic procedure (which should become a part of SRFI 165 in its next draft):
(define (bind/forked computation . proc*)
(apply bind
(local environment-copy computation)
proc*))
"bind/forked" combines "bind" (from SRFI 165) and "forked" (from SRFI 159/165): (bind/forked computation proc1 ...) is like (bind computation proc1 ...), with the difference that bind/forked executes computation in a copy of the environment.
The following formatter just updates the state variables "row" and "col" (and could be used by the default output). (Note that I am using "make-computation" to create a formatter so that I can use "string-for-each", which is in R7RS-small.)
(define (hidden str)
(fn ((string-width string-width))
(make-computation
(lambda (format)
(string-for-each
(lambda (ch)
(if (char=? ch #\newline)
(format (fn ((%row row))
(with! (row (+ %row 1))
(col 0))))
(format (fn ((%col col))
(with! (col (+ %col (string-width (string ch)))))))))
str)))))
The interesting procedure is the following (and is basically doing what "call-with-output-generator" is doing in the reference implementation:
(define (with-output-generator fmt)
(make-computation
(lambda (format)
(make-coroutine-generator
(lambda (yield)
(format (with ((output
(lambda (str)
(yield str)
(hidden str))))
(bind/forked fmt))))))))