;;; lexical-binding: t

(iter-defun cross-through-multiples-of (n)
  "Repeat indefinitely: Return `t' N-1 times, then return `nil' once."
  (let ((i (1- n)))
    (while t
      (if (zerop i)  (progn (setq i (1- n)) (iter-yield nil))
        (iter-yield t)
        (cl-decf i)))))

(iter-defun make-prime-gen ()
  "Return a generator of the prime numbers."
  (let ((n 2) (sieve '()))
    (while t
      (when (cl-every #'identity (mapcar #'iter-next sieve))
        ;; a new prime!
        (push (cross-through-multiples-of n) sieve)
        (iter-yield n))
      (cl-incf n))))

(iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)
  "Return an iterator of files in DIRECTORY.
The arguments FULL, MATCH and NOSORT are like in
`directory-files'.  Forth optional arg RECURSE non-nil means
recurse on subdirectories.  If RECURSE is a function, it should
accept one argument, a directory file name, and return non-nil
when we should recurse into that directory.  Any other non-nil
value means recurse into every readable subdirectory."
  (when (file-accessible-directory-p) ; i.e. DIRECTORY is readable
    (let ((files (directory-files directory full match nosort))  file)
      (while (setq file (pop files))
        (cond
         ((not (file-directory-p file))
          (iter-yield file))
         ((member (file-name-nondirectory (directory-file-name file)) '("." "..")))
         (t
          (iter-yield file)
          (when (or (and (functionp recurse)
                         (funcall recurse file))
                    recurse)
            (iter-yield-from (iterator-of-directory-files file full match nosort recurse)))))))))

