# Re: Defining AVERAGING clause

I shouldn't have used mapc as an example. Consider instead some random,
opaque, map-like function that couldn't be rewritten into an iter form. In
any case, your collectors library seems interesting. Will check it out,
thanks!

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

> Here are two different ways of rewriting that mapc with iter:
>
> `(iter top (repeat 1) (iter (for x in '(1 2 3)) (in top (collect x))))`
>
> `(iter (repeat 1) (appending '(1 2 3)))`
>
> `(iter (repeat 1) (appending (iter (for x in '(1 2 3)) (collect x))))`
>
> If I am using iter, I try hard to *only* use iter, as one of the reasons
> for this library (for me) is to have a single syntax for iteration.
>
> That said, I wrote the `collectors` library to handle arbitrary collection
> tasks that were not easily expressed as a straight iteration.
> The collectors library binds local functions, so you can `(mapc #'collect
> ...)` etc.
>
> https://github.com/AccelerationNet/collectors
>
> Cheers,
>
> Russ Tyndall
>
> On 03/13/2018 11:52 AM, Luís Oliveira wrote:
>
> 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 <r...@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
>>
>>
>>
>