Defining AVERAGING clause

Russ Tyndall russ at acceleration.net
Wed Mar 14 16:13:49 UTC 2018


I think the natural ordering of things means this wont be a problem in 99% of situations. Obviously you cant use mean until the finally clause, but all of your finally's should come after the averaging finally.

(iterate:defmacro-clause (averaging expr &optional into var)
  (let ((avg (or var iterate::*result-var*)))
    (alexandria:with-unique-names (cnt sum)
      `(progn
        (with ,avg)
        (with ,sum = 0)
        (with ,cnt = 0)
        (incf ,cnt)
        (incf ,sum ,expr)
        
        (finally
         (setf ,avg (if (plusp ,cnt) (/ ,sum ,cnt) 0))
         )))))

(iter (for i from 0 to 100)
      (averaging i into mean)
      (finally (return mean)))
=> 50

Expands to:
(LET* ((I NIL) (MEAN NIL) (#:SUM4008 0) (#:CNT4007 0))
  (BLOCK NIL
    (TAGBODY
      (PROGN (SETQ I -1))
     LOOP-TOP-NIL
      (PROGN
       (SETQ I (+ I 1))
       (IF (> I 100)
           (GO LOOP-END-NIL))
       (PROGN
        (SETQ #:CNT4007 (+ 1 #:CNT4007))
        (SETQ #:SUM4008 (+ I #:SUM4008))))
      (PROGN)
      (GO LOOP-TOP-NIL)
     LOOP-END-NIL
      (PROGN
       (SETF MEAN
               (IF (PLUSP #:CNT4007)
                   (/ #:SUM4008 #:CNT4007)
                   0))
       (RETURN MEAN)))
    NIL))

Cheers,
Russ Tyndall
Acceleration.net


----- Original Message -----
From: Robert Goldman [mailto:rpgoldman at sift.info]
To: russ at acceleration.net
Cc: iterate-devel at common-lisp.net
Sent: Tue, 13 Mar 2018 12:27:47 -0500
Subject: Re: Defining AVERAGING clause

Wouldn't this technique have trouble with code movement issues?  For 
example, if I have
```
(iter (for x in data-table)
    (averaging x into mean)
    (finally (return mean)))
```
I know that's a contrived example, but I think the point is clear: if 
I'm going to make `averaging` a collector, I'd like to be able to use 
its result, and if that result is computed in a `finally` block that's 
invisible and out of my control, I can't do it, can I?  There's 
`finally-protected`, but I think that's the *opposite* of what I need.

Best,
r


On 13 Mar 2018, at 10:08, Russ Tyndall 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
>>





-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/iterate-devel/attachments/20180314/83873bfc/attachment.html>


More information about the iterate-devel mailing list