123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- ;;;; iterators.lisp
- (defpackage #:iterators-simple
- (:use :cl)
- (:export #:with-iterator
- #:call-iterator
- #:define-iterator
- #:create-iterator))
- (in-package #:iterators-simple)
- ;;; "iterators" goes here. Hacks and glory await!
- (defun make-numeric-iterator (function second-argument &optional (initial 1))
- "Create a closure acting as a numeric iterator.
- This takes a FUNCTION, a SECOND-ARGUMENT to a function,
- and an INITIAL value for N defaulting at 1.
- This applies the function to N, and the SECOND-ARGUMENT,
- setting N to the value."
- (let ((n initial))
- #'(lambda ()
- (setf n (funcall function n second-argument)))))
- (defun make-stream-iterator (stream-or-file-name type)
- (let ((stream (if (stringp stream-or-file-name)
- (open stream-or-file-name)
- stream-or-file-name)))
- (ecase type
- (:line
- #'(lambda ()
- (read-line stream nil nil)))
- (:char
- #'(lambda ()
- (read-char stream nil nil)))
- (:byte
- #'(lambda ()
- (read-byte stream nil nil))))))
- (defun make-list-iterator (&rest list)
- (let ((list list))
- #'(lambda ()
- (if (= 0 (length list))
- nil
- (pop list)))))
- (defun call-iterator (iterator)
- (funcall iterator))
- (defun create-iterator (type &rest args)
- "Create an integer of type TYPE, using args ARGS."
- (ecase type
- (:numeric
- (make-numeric-iterator (elt args 0) (elt args 1) (if (elt args 2) (elt args 2) 1)))
- (:stream
- (make-stream-iterator (elt args 0) (elt args 1)))
- (:list
- (apply #'make-list-iterator args))))
- (defmacro with-iterator ((name type &rest args) &body body)
- (let ((iterator-expression (ecase type
- (:numeric
- `(make-numeric-iterator ,(elt args 0) ,(elt args 1) ,(if (elt args 2) (elt args 2) 1)))
- (:stream
- `(make-stream-iterator ,(elt args 0) ,(elt args 1)))
- (:list
- `(make-list-iterator ,@args)))))
- `(let ((,name ,iterator-expression))
- (flet ((,name ()
- (call-iterator ,name)))
- ,@body))))
- (defmacro define-iterator (name type &rest args)
- (let ((iter-expression (ecase type
- (:numeric
- `(make-numeric-iterator ,(elt args 0) ,(elt args 1) ,(if (elt args 2) (elt args 2) 1)))
- (:stream
- `(make-stream-iterator ,(elt args 0) ,(elt args 1)))
- (:list
- `(make-list-iterator ,@args)))))
- `(defvar ,name ,iter-expression)))
|