Just a curiosity: you could compute the average incrementally: <https://math.stackexchange.com/questions/106700/incremental-averageing>, but doing it the usual way is probably more efficient and with smaller numeric error when using floats.

Slightly off-topic question: oftentimes I have to use map-like iterators. Is there a good way to use such iterators in conjunction with iter? An obvious way would be something like:

    (iter (repeat 1) (mapc (lambda (x) (collect x)) '(1 2 3)))

The (iter (repeat 1) ...) bit could be hidden under a macro, I suppose. But it'd be nicer if collect were a function, so I could do (mapc #'collect '(1 2 3)). Perhaps said macro could rewrite #'clause to (lambda (x) (expansion-of-clause x)) or something similar. Looks like a fun idea to explore so I'm wondering if someone's played with something like this before.

(It's even more fun to turn map-like iterators into generators using continuations, but that's fully off-topic. :-))

Cheers,
Luís

On Tue, Mar 13, 2018 at 3:08 PM Russ Tyndall <russ@acceleration.net> wrote:

Here is an existing "sampling" clause to pull a random sample from a larger data set.  The long and short is just use a finally clause, as you would when writing a normal iterate loop.

(iterate:defmacro-clause (sampling expr &optional into var size size)
  "resevoir sample the input"
  (let ((sample (or var iterate::*result-var*)))
    (alexandria:with-unique-names (i sample-size sigil buffer row)
      `(progn
        (with ,sample)
        (with ,sample-size = (or ,size 100))
        (with ,buffer = (make-array ,sample-size :initial-element ',sigil))
        (with ,i = 0)
        (if (< ,i ,sample-size)
            (setf (aref ,buffer ,i) ,expr)
            (let ((r (random ,i)))
              (when (< r ,sample-size)
                (setf (aref ,buffer r) ,expr))))
        (incf ,i)
        (finally
         ;; convert our sample to a list, but only if we actually took the sample
         (when (plusp ,i)
           (setf ,sample
                 (iter (for ,row in-vector ,buffer)
                   (until (eq ,row ',sigil))
                   (collect ,row)))))))))

Cheers,
Russ Tyndall
Acceleration.net

On 03/13/2018 10:49 AM, Robert Goldman wrote:

I was going to define an AVERAGING collector clause for iterate, but I'm not sure how to do it. The obvious thing, it seemed to me, would be to sum the values as I go along, and count them, and then divide the sum by the count when leaving the loop.

But the examples for DEFMACRO-CLAUSE in the manual do all of their work while iterating, and there doesn't seem to be an "at-end" hook. Is the kind of thing I would like feasible, and if so, how is it to be done?

thanks!
r