<?xml version="1.0"?>
<paste-with-annotations>
  <paste>
    <number>
      <integer>60780</integer>
    </number>
    <user>
      <string>wybiral</string>
    </user>
    <title>
      <string>iterators</string>
    </title>
    <contents>
      <string>(defun all (func lst)
  &quot;True if func evaluates true for all in lst&quot;
  (if (not lst) t
      (and (funcall func (car lst))
           (all func (cdr lst)))))

(defun irange (start stop step)
  &quot;Iterator for (start &lt;= i &lt; stop) incremented by step&quot;
  (if (&lt;= stop start) nil
      (cons start
            (lambda ()
              (irange (+ start step)
                      stop
                      step)))))

(defun ifrom (i step)
  &quot;Start at i, infinitely increase by step&quot;
  (cons i (lambda () (ifrom (+ i step) step))))

(defun ilist (lst)
  &quot;Iterate over list&quot;
  (if (not lst) nil
      (cons (car lst)
            (lambda ()
              (ilist (cdr lst))))))

(defun imap (func iter)
  &quot;Iterator, mapping over an iterator&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (if (not next) nil
        (cons (funcall func i)
              (lambda ()
                (imap func
                       (funcall next)))))))

(defun ilimit (n iter)
  &quot;Limit iteration to n elements&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (if (not next) nil
        (if (= n 0) nil
            (cons i
                  (lambda ()
                    (ilimit (- n 1)
                            (funcall next))))))))

(defun ifirst (func iter)
  &quot;Return the first element for which func is true&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (if (not next) nil
        (if (funcall func i) i
            (ifirst func (funcall next))))))

(defun iuntil (func iter)
  &quot;Iterate until func returns true for element&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (if (not next) nil
        (if (funcall func i) nil
            (cons i
                  (lambda ()
                    (iuntil func
                          (funcall next))))))))

(defun iwhile (func iter)
  &quot;Iterate while func returns true, otherwise stop&quot;
  (iuntil (lambda (x)
            (not (funcall func x)))
          iter))

(defun lmap (func iter)
  &quot;Map an iterator to a list&quot;
  (let ((i (car iter)) (next (cdr iter)))
    (if (not next) nil
        (cons (funcall func i)
              (lmap func
                     (funcall next))))))
  
(defun ifilter (func iter)
  &quot;Iterator filtering iterator&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (if (not next) nil
        (if (funcall func i)
            (cons i
                  (lambda ()
                    (ifilter func
                             (funcall next))))
            (ifilter func
                     (funcall next))))))

(defun ireduce (func iter)
  &quot;Reduce an iterator&quot;
  (let ((i (car iter))
        (next (cdr iter)))
    (let ((iter2 (funcall next)))
      (let ((i2 (car iter2))
            (next2 (cdr iter2)))
        (if (not next2)i
            (ireduce func
                     (cons (funcall func i i2)
                           next2)))))))

(defun isum (iter)
  (ireduce #'+ iter))

(defun ireverse (iter)
  &quot;Create a reverse iterator&quot;
  (ilist (reverse (lmap #'identity
                         iter))))


(defun ifor (func iter)
  &quot;Do func on each in iter&quot;
  (if iter
      (progn (funcall func (car iter))
             (ifor func
                       (funcall (cdr iter))))))

(defun izip (&amp;rest args)
  &quot;Zip iterators together, output as list of ith items&quot;
  (labels ((get-args (lst)
             (if (not lst) nil
                 (cons (caar lst)
                       (get-args (cdr lst)))))
           (get-list (lst)
             (if (not lst) nil
                 (let ((next (funcall (cdr (car lst)))))
                   (if (not next) 'stop
                       (let ((tail (get-list (cdr lst))))
                         (if (eq tail 'stop) 'stop
                             (cons (cons (car next)
                                         (cdr next))
                                   tail)))))))
           (inner-izip (lst)
             (let ((next (get-list lst)))
               (if (eq next 'stop)
                   (cons (get-args lst)
                         (lambda () nil))
                   (cons (get-args lst)
                         (lambda () (inner-izip next)))))))
  (inner-izip args)))

(defun ilast (iter)
  &quot;Iterate ENTIRE sequence, return last&quot;
  (let ((next (funcall (cdr iter))))
    (if (not next) (car iter)
        (ilast next))))

(defun ifib ()
  &quot;Infinite Fibonacci iterator&quot;
  (labels ((inner-ifib (a b)
             (cons a (lambda ()
                       (inner-ifib b
                                   (+ a b))))))
    (inner-ifib 1 1)))

(defun iprimes ()
  &quot;Infinite prime iterator&quot;
  (labels ((inner (i found)
             (if (all (lambda (x)
                         (not (= (mod i x) 0))) found)
                 (cons i (lambda ()
                           (inner (+ i 1) (append found (list i)))))
                 (inner (+ i 1) found))))
    (inner 2 nil)))
</string>
    </contents>
    <universal-time>
      <integer>3419788808</integer>
    </universal-time>
    <channel>
      <string>None</string>
    </channel>
    <colorization-mode>
      <string>Common Lisp</string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
  </paste>
</paste-with-annotations>