util/iter: allow stopping an iterator by setting its stop slot to t

This commit is contained in:
Helmut Merz 2024-09-09 19:52:19 +02:00
parent 18bfcd8224
commit 60cee40051

View file

@ -5,36 +5,38 @@
(defpackage :scopes/util/iter (defpackage :scopes/util/iter
(:use :common-lisp) (:use :common-lisp)
(:export #:next #:value #:next-value #:process (:export #:stop #:next #:value #:next-value #:process
#:list-iterator)) #:list-iterator))
(in-package :scopes/util/iter) (in-package :scopes/util/iter)
;;;; iterators ;;;; iterators
(defclass abstract-iterator () ()) (defclass iterator ()
((stop :accessor stop :initform nil)))
(defgeneric next (it)) (defgeneric next (it))
(defgeneric value (it)) (defgeneric value (it))
(defgeneric next-value (it) (defgeneric next-value (it)
(:method ((it abstract-iterator)) (:method ((it iterator))
(next it) (next it)
(value it))) (value it)))
(defgeneric process (it fn &optional stop) (defgeneric process (it fn)
(:method ((it abstract-iterator) fn &optional (stop (constantly nil))) (:method ((it iterator) fn)
(do ((eoi (next it) (next it))) (do ((eoi (next it) (next it)))
((or eoi (funcall stop))) ((or eoi (stop it)))
(funcall fn (value it))))) (funcall fn (value it)))
(setf (stop it) nil)))
;;;; list iterator implementation ;;;; list iterator implementation
(defclass list-iterator (abstract-iterator) (defclass list-iterator (iterator)
((data :reader data :initarg :data :initform nil) ((data :reader data :initarg :data :initform nil)
(cur :accessor cur))) (cur :accessor cur)))
(defmethod initialize-instance :after ((it list-iterator) &key &allow-other-keys) (defmethod initialize-instance :after ((it list-iterator) &key)
(setf (cur it) (cons nil (data it)))) (setf (cur it) (cons nil (data it))))
(defmethod next ((it list-iterator)) (defmethod next ((it list-iterator))