Hi
During my experimenting with the Scheme, I found that the I/O ****ts
are not so usable with recursive programming approach. The ****ts
encapsulate a state - once you read a character it cannot be re-read
once again and another read-char call returns the next character in
the underlying stream. On the other hand lists provide another
mechanism which is quite comfortable to use with recursion - car
returns the first element and cdr returns the rest of the list.
I tried to master a kind of cache for the Scheme input ****ts whose
interface resembles car/cdr. There are two basic functions - get-char
which returns the first character in the cache and get-next which can
be used in recursion for further get-char calls. I used set-cdr! to
mutate the list tail. Thus the ****t reading looks like working with a
recursive structure.
; the first element is always an input ****t
; the rest of the list is file data
(define (make-cache input-****t)
(list input-****t (read-char input-****t)))
; just return the first char in the cache which is
; the second element in the list
(define (get-char cache)
(cadr cache))
(define (get-next cache)
(let
((input-****t (car cache))
(buffer (cdr cache)))
(if (null? (cdr buffer))
; mutate the list tail by adding another character from the file
(set-cdr! buffer (list (begin
(display "read-char\n")
(read-char input-****t)))))
(cons input-****t (cdr buffer))))
; test function
(define (file-length cache)
(letrec
((fl (lambda (cache len)
(let
((c (get-char cache)))
(cond
((eof-object? c) len)
(else (fl (get-next cache) (+ 1 len))))))))
(fl cache 0)))
The test function file-length uses a proper recursion. I added
(display "read-char\n") to trace the file reads, so if you run file-
length twice, you will not see "read-char" printouts in the second
time.
I'm a newbie in Scheme. What do you gurus think about this approach?
Is it safe? Might it be useful?
Thank you
Sergey