<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8">
</head>
<body>
<div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">On 14 Mar 2018, at 11:13, Russ Tyndall wrote:</p>
</div>
<div style="white-space:normal"><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px"><p dir="auto">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.</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">Agreed. Still, it's kind of an unhappy feeling to be relying on this not very user-controlled behavior, and if some day downstream it goes wrong, that would be problematic.</p>
<p dir="auto">I guess one would want to be able to build <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">finally</code> and <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">initially</code> clauses with <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">defmacro-clause</code> where you could specify whether they come before all end-programmer clauses of the same type, or before all such clauses of the same type. I suppose one could add sorting to the <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">final-code</code> and <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">init-code</code> in <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">iter</code>, but that seems fraught with peril. You're probably right that I should just not worry about this.</p>
</div>
<div style="white-space:normal"><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px"><p dir="auto">(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 [<a href="mailto:rpgoldman@sift.info" style="color:#777">mailto:rpgoldman@sift.info</a>]<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>
</p>
<blockquote style="border-left:2px solid #777; color:#999; margin:0 0 5px; padding-left:5px; border-left-color:#999"><p dir="auto">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:</p>
<blockquote style="border-left:2px solid #777; color:#BBB; margin:0 0 5px; padding-left:5px; border-left-color:#BBB"><p dir="auto">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>
</p>
</blockquote></blockquote></blockquote></div>
<div style="white-space:normal">
</div>
</div>
</body>
</html>