[scm/utilities] even more efficient list-flatten functions

because:

* list? is O(N), because it needs to test for an improper
list. improper lists are lists whose last pair's cdr cell is not
'(). null? and pair? are both O(1).

* avoids reverse which is also O(N): guile has unlimited stack
therefore we can do non-tail-call loop first to pass as parameter to
the tail-call loop. this removes the need for prepend-and-reverse.
This commit is contained in:
Christopher Lam 2019-11-18 21:19:50 +08:00
parent 043abcb436
commit fbc7c9027e
2 changed files with 8 additions and 7 deletions

View File

@ -107,7 +107,8 @@
(define (gnc:html-document-tree-collapse . tree)
(let lp ((e tree) (accum '()))
(cond ((list? e) (fold lp accum e))
(cond ((null? e) accum)
((pair? e) (fold lp accum e))
((string? e) (cons e accum))
(else (cons (object->string e) accum)))))

View File

@ -212,14 +212,14 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; flattens an arbitrary deep nested list into simple list. this is
;; probably the most efficient algorithm available. '(1 2 (3 4)) -->
;; '(1 2 3 4)
;; '(1 2 3 4) thanks to manumanumanu on #guile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (gnc:list-flatten . lst)
(reverse
(let lp ((e lst) (accum '()))
(if (list? e)
(fold lp accum e)
(cons e accum)))))
(let loop ((lst lst) (acc '()))
(cond
((null? lst) acc)
((pair? lst) (loop (car lst) (loop (cdr lst) acc)))
(else (cons lst acc)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; compatibility hack for fixing guile-2.0 string handling. this code