Imagine a UTF-8 decoder that takes a list of bytes and returns human-readable code points like:
> (utf-8->human-readable-code-points '(32 32 195 160 160))
("u+0020" "u+0020" "u+00E0" ("Error: trailing byte without preceding start byte" 160))
This list builder functionality is meant for that function:
;; a list builder will allow us to build a list
;; by successively adding to the end without retracing
;; the list each time. And without having a stack of
;; cons calls to unwind. Will allow constructing a list
;; in order in a tail call fashion
;; (list-builder 'add! item) -- returns list so far
;; (list-builder 'list) -- returns list so far
(define (make-list-builder)
(let [(list-under-construction '())
(last-cons-cell '())]
(lambda (dispatch . parameters)
(case dispatch
[(add!) (if (null? list-under-construction)
(begin
(set! list-under-construction (list (car parameters)))
(set! last-cons-cell list-under-construction))
(let ((new-cons-cell (list (car parameters))))
(set-cdr! last-cons-cell new-cons-cell)
(set! last-cons-cell new-cons-cell)))
list-under-construction]
[(list) list-under-construction]
[else (error "unmatched dispatch" dispatch)]))))
Sample use:
> (define lb (make-list-builder))
> (lb 'list)
()
> (lb 'add! "here's an atom")
("here's an atom")
> (lb 'add! '(here's a list))
("here's an atom" (here 's a list))
Questions for review:
Is there a standard scheme function or way of doing this that I missed? The problem I am trying to ultimately solve can't be solved by a map because a map produces a list of the same size as the input, and map does not guarantee the order that elements of a Lisp or processed. Googling and searching Stack Overflow for scheme list builder or scheme list accumulater did not return useful results.
Is
make-list-builder
expressed in idiomatic Scheme?How would you improve
make-list-builder
, or what would you do differently?