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.<br/><br/>(iterate:defmacro-clause (averaging expr &optional into var)<br/>  (let ((avg (or var iterate::*result-var*)))<br/>    (alexandria:with-unique-names (cnt sum)<br/>      `(progn<br/>        (with ,avg)<br/>        (with ,sum = 0)<br/>        (with ,cnt = 0)<br/>        (incf ,cnt)<br/>        (incf ,sum ,expr)<br/>        <br/>        (finally<br/>         (setf ,avg (if (plusp ,cnt) (/ ,sum ,cnt) 0))<br/>         )))))<br/><br/>(iter (for i from 0 to 100)<br/>      (averaging i into mean)<br/>      (finally (return mean)))<br/>=> 50<br/><br/>Expands to:<br/>(LET* ((I NIL) (MEAN NIL) (#:SUM4008 0) (#:CNT4007 0))<br/>  (BLOCK NIL<br/>    (TAGBODY<br/>      (PROGN (SETQ I -1))<br/>     LOOP-TOP-NIL<br/>      (PROGN<br/>       (SETQ I (+ I 1))<br/>       (IF (> I 100)<br/>           (GO LOOP-END-NIL))<br/>       (PROGN<br/>        (SETQ #:CNT4007 (+ 1 #:CNT4007))<br/>        (SETQ #:SUM4008 (+ I #:SUM4008))))<br/>      (PROGN)<br/>      (GO LOOP-TOP-NIL)<br/>     LOOP-END-NIL<br/>      (PROGN<br/>       (SETF MEAN<br/>               (IF (PLUSP #:CNT4007)<br/>                   (/ #:SUM4008 #:CNT4007)<br/>                   0))<br/>       (RETURN MEAN)))<br/>    NIL))<br/><br/>Cheers,<br/>Russ Tyndall<br/>Acceleration.net<br/><br/><br/>----- Original Message -----<br/>From: Robert Goldman [mailto:rpgoldman@sift.info]<br/>To: russ@acceleration.net<br/>Cc: iterate-devel@common-lisp.net<br/>Sent: Tue, 13 Mar 2018 12:27:47 -0500<br/>Subject: Re: Defining AVERAGING clause<br/><br/>Wouldn't this technique have trouble with code movement issues?  For <br/>example, if I have<br/>```<br/>(iter (for x in data-table)<br/>    (averaging x into mean)<br/>    (finally (return mean)))<br/>```<br/>I know that's a contrived example, but I think the point is clear: if <br/>I'm going to make `averaging` a collector, I'd like to be able to use <br/>its result, and if that result is computed in a `finally` block that's <br/>invisible and out of my control, I can't do it, can I?  There's <br/>`finally-protected`, but I think that's the *opposite* of what I need.<br/><br/>Best,<br/>r<br/><br/><br/>On 13 Mar 2018, at 10:08, Russ Tyndall wrote:<br/><br/>> Here is an existing "sampling" clause to pull a random sample from a <br/>> larger data set.  The long and short is just use a finally clause, as <br/>> you would when writing a normal iterate loop.<br/>><br/>> (iterate:defmacro-clause (sampling expr &optional into var size size)<br/>>   "resevoir sample the input"<br/>>   (let ((sample (or var iterate::*result-var*)))<br/>>     (alexandria:with-unique-names (i sample-size sigil buffer row)<br/>>       `(progn<br/>>         (with ,sample)<br/>>         (with ,sample-size = (or ,size 100))<br/>>         (with ,buffer = (make-array ,sample-size <br/>> :initial-element ',sigil))<br/>>         (with ,i = 0)<br/>>         (if (< ,i ,sample-size)<br/>>             (setf (aref ,buffer ,i) ,expr)<br/>>             (let ((r (random ,i)))<br/>>               (when (< r ,sample-size)<br/>>                 (setf (aref ,buffer r) ,expr))))<br/>>         (incf ,i)<br/>>         (finally<br/>>          ;; convert our sample to a list, but only if we <br/>> actually took the sample<br/>>          (when (plusp ,i)<br/>>            (setf ,sample<br/>>                  (iter (for ,row in-vector ,buffer)<br/>>                    (until (eq ,row ',sigil))<br/>>                    (collect ,row)))))))))<br/>><br/>> Cheers,<br/>> Russ Tyndall<br/>> Acceleration.net<br/>> On 03/13/2018 10:49 AM, Robert Goldman wrote:<br/>>><br/>>> I was going to define an |AVERAGING| collector clause for iterate, <br/>>> but I'm not sure how to do it. The obvious thing, it seemed to me, <br/>>> would be to sum the values as I go along, and count them, and then <br/>>> divide the sum by the count when leaving the loop.<br/>>><br/>>> But the examples for |DEFMACRO-CLAUSE| in the manual do all of their <br/>>> work while iterating, and there doesn't seem to be an "at-end" hook. <br/>>> Is the kind of thing I would like feasible, and if so, how is it to <br/>>> be done?<br/>>><br/>>> thanks!<br/>>> r<br/>>><br/><br/><br/><br/><br/><br/>