list-accumulator.lisp 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. ;;;; list-accumulator.lisp
  2. (in-package #:list-accumulator)
  3. (proclaim '(optimize))
  4. ;;; TAIL-RECURSIVE LIST-EATERS
  5. ;;; Return a tail-recursive list-eater function.
  6. ;;; FN should modify the accumulator ACC.
  7. ;;; ACC-INIT specifies initial value for ACC.
  8. (defun list-accumulator (fn &optional acc-init)
  9. "Return a recursive lambda for recurring on cdrs."
  10. (genlambda (lst &optional (acc acc-init))
  11. (if lst
  12. ;; If LST is not nil, recur on CDR.
  13. (rec (cdr lst)
  14. (funcall fn
  15. (car lst)
  16. acc))
  17. ;; Return ACC at end of list.
  18. acc)))
  19. ;;; Create a LACC with anaphoric reference to
  20. ;;; (CAR LST) as IT and the accumulator, ACC.
  21. ;;; The BODY will comprise the contents of the
  22. ;;; FN in LACC.
  23. (defmacro anaphoric-list-accumulator (acc-init &body body)
  24. "Anaphoric wrapper for list-accumulator with smybol macrolet for ."
  25. `(lacc #'(lambda (it acc)
  26. (macrolet (,@lacc::*macrolets*)
  27. (symbol-macrolet (,@lacc::*symbols*)
  28. ,@body)))
  29. ,acc-init))
  30. ;;; Wrapper for ALACC to embed within DEFUN or DEFMACRO.
  31. (defmacro accumulate-from-list (lst acc-init &body body)
  32. "Call a function to recur on CDRs of LST."
  33. `(funcall (anaphoric-list-accumulator ,acc-init ,@body) ,lst))