iterators.lisp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. ;;;; iterators.lisp
  2. (defpackage #:iterators-simple
  3. (:use :cl)
  4. (:export #:with-iterator
  5. #:call-iterator
  6. #:define-iterator
  7. #:create-iterator))
  8. (in-package #:iterators-simple)
  9. ;;; "iterators" goes here. Hacks and glory await!
  10. (defun make-numeric-iterator (function second-argument &optional (initial 1))
  11. "Create a closure acting as a numeric iterator.
  12. This takes a FUNCTION, a SECOND-ARGUMENT to a function,
  13. and an INITIAL value for N defaulting at 1.
  14. This applies the function to N, and the SECOND-ARGUMENT,
  15. setting N to the value."
  16. (let ((n initial))
  17. #'(lambda ()
  18. (setf n (funcall function n second-argument)))))
  19. (defun make-stream-iterator (stream-or-file-name type)
  20. (let ((stream (if (stringp stream-or-file-name)
  21. (open stream-or-file-name)
  22. stream-or-file-name)))
  23. (ecase type
  24. (:line
  25. #'(lambda ()
  26. (read-line stream nil nil)))
  27. (:char
  28. #'(lambda ()
  29. (read-char stream nil nil)))
  30. (:byte
  31. #'(lambda ()
  32. (read-byte stream nil nil))))))
  33. (defun make-list-iterator (&rest list)
  34. (let ((list list))
  35. #'(lambda ()
  36. (if (= 0 (length list))
  37. nil
  38. (pop list)))))
  39. (defun call-iterator (iterator)
  40. (funcall iterator))
  41. (defun create-iterator (type &rest args)
  42. "Create an integer of type TYPE, using args ARGS."
  43. (ecase type
  44. (:numeric
  45. (make-numeric-iterator (elt args 0) (elt args 1) (if (elt args 2) (elt args 2) 1)))
  46. (:stream
  47. (make-stream-iterator (elt args 0) (elt args 1)))
  48. (:list
  49. (apply #'make-list-iterator args))))
  50. (defmacro with-iterator ((name type &rest args) &body body)
  51. (let ((iterator-expression (ecase type
  52. (:numeric
  53. `(make-numeric-iterator ,(elt args 0) ,(elt args 1) ,(if (elt args 2) (elt args 2) 1)))
  54. (:stream
  55. `(make-stream-iterator ,(elt args 0) ,(elt args 1)))
  56. (:list
  57. `(make-list-iterator ,@args)))))
  58. `(let ((,name ,iterator-expression))
  59. (flet ((,name ()
  60. (call-iterator ,name)))
  61. ,@body))))
  62. (defmacro define-iterator (name type &rest args)
  63. (let ((iter-expression (ecase type
  64. (:numeric
  65. `(make-numeric-iterator ,(elt args 0) ,(elt args 1) ,(if (elt args 2) (elt args 2) 1)))
  66. (:stream
  67. `(make-stream-iterator ,(elt args 0) ,(elt args 1)))
  68. (:list
  69. `(make-list-iterator ,@args)))))
  70. `(defvar ,name ,iter-expression)))