|
@@ -0,0 +1,81 @@
|
|
|
+;;;; 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)))
|