[alexandria-devel] Fold operators on lists and trees in Alexandria?
Heka Treep
zena.treep at gmail.com
Sat Aug 7 21:42:41 UTC 2010
Sorry, I made a small typo:
(defun flatten/fold-rigth (list)
(fold-rigth #'(lambda (e rest)
(typecase e
(atom (cons e rest))
- (list (append (flatten e) rest))
+ (list (append (flatten/fold-rigth e) rest))))
list nil))
But this, of course, does not affect the benchmark.
2010/8/8 Heka Treep <zena.treep at gmail.com>
> Hi.
>
> I was found that there is no effective fold operators on lists or trees in
> CL. I know that `reduce' can do this (as an article in Wikipedia sayz) but
> `reduce' is not very effective. As stated in the Graham Hutton's article
> ``fold is a standard operator that encapsulates a simple pattern of
> recursion for processing lists'', also catamorphism at some ADT plays the
> same role. So I thought that if we introduce an effective fold operators, it
> becomes possible to express many functions through its shortly and
> effectively (in fact, almost any function on that ADT).
>
> Take for example the `flatten' function that is defined in Alexandria as
> follows:
>
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;; ok, TCO recursion:
> ;;
> (defun flatten (tree)
> (let (list)
> (labels ((traverse (subtree)
> (when subtree
> (if (consp subtree)
> (progn
> (traverse (car subtree))
> (traverse (cdr subtree)))
> (push subtree list)))))
> (traverse tree))
> (nreverse list)))
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> We need an ADT for the trees, but in the first approximation we can use
> nested lists.
>
> When expressed in terms of reduce:
>
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (defun flatten/reduce (list)
> (reduce #'(lambda (e rest)
> (typecase e
> (atom (cons e rest))
> (list (append (flatten/reduce e) rest))))
> list
> :initial-value nil
> :from-end t))
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> Now if we translate pure functional operator (here is `reduce') to the
> instructions for tagbody/go "state machine":
>
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;;; fold-left f '(a b c) i
> ;;;
> ;;; f
> ;;; /\
> ;;; f c
> ;;; /\
> ;;; f b
> ;;; /\
> ;;; i a
> ;;;
> ;;; foldl f z [] = z
> ;;; foldl f z (x:xs) = foldl f (f z x) xs
>
> (defun fold-left (function list &optional initial-value)
> (let ((result initial-value))
> (tagbody
> :start
> (unless (endp list)
> (setq result (funcall function result (car list)))
> (setq list (cdr list))
> (go :start)))
> result))
>
> ;;; fold-rigth f '(a b c) i
> ;;;
> ;;; f
> ;;; /\
> ;;; a f
> ;;; /\
> ;;; b f
> ;;; /\
> ;;; c i
> ;;;
> ;;; foldr f z [] = z
> ;;; foldr f z (x:xs) = f x (foldr f z xs)
>
> (defun fold-rigth (function list &optional initial-value)
> (let ((result initial-value)
> (list (nreverse list)))
> (tagbody
> :start
> (unless (endp list)
> (setq result (funcall function (car list) result))
> (setq list (cdr list))
> (go :start)))
> result))
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> Then `flatten' can be written as:
>
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (defun flatten/fold-rigth (list)
> (fold-rigth #'(lambda (e rest)
> (typecase e
> (atom (cons e rest))
> (list (append (flatten e) rest))))
> list nil))
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> I try to benchmarc (this three functions) and has the following results:
>
> flatten/fold-rigth
>
> X time
> Y memory
>
> alexandria:flatten
>
> 10 * X time
> 23 * Y memory
>
> flatten/reduce
>
> 42 * X time
> 83 * Y memory
>
> So, its look resonable to use folders there.
>
>
>
> ((sorry for my english - I just using google.translate :))
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/alexandria-devel/attachments/20100808/2b704507/attachment.html>
More information about the alexandria-devel
mailing list