On Sat, Feb 12, 2005 at 12:44:05PM -0500, Uri Guttman wrote:
: >>>>> "JG" == Joe Gottman <[EMAIL PROTECTED]> writes:
: 
:   JG>    sub use_first() 
:   JG>    {
:   JG>         for 1..2 {
:   JG>                 FIRST {say 'entering loop';}
:   JG>                 say $_; 
:   JG>                 LAST    {say 'leaving loop';}
:   JG>         }
:   JG>   }
: 
:   JG> The first time use_first is called it will print
:   JG>         entering loop
:   JG>         1
:   JG>         2
:   JG>         leaving loop
: 
:   JG> but subsequently it will print
:   JG>         1
:   JG>         2
:   JG>         leaving loop
: 
: that seems to imply that FIRST is a program level first time action. i
: think it does what you want and is executed on the first iteration of a
: loop, each time the loop is started up. it is symmetrical to LAST in
: that way. it should print the former text each time the sub is called.
: 
: but i could be wrong. :)

What's going on here is that the loop body is a closure that is
cloned upon entry to the loop (you're logically passing a closure
to the "for()" function that implements the loop), so if there's a
FIRST inside, it runs each time the loop is initialized.  Likewise
state variables are logically regenerated for closure clones, so if
use_first() above wants to have a state variable that is maintained
from call to call, it must put it *outside* the loop.

Also, note that a LAST block, if any, has to be called from within
the implementation of for(), since only for() knows when it's done
with the loop as a whole.

It will be an interesting problem for the optimizer to figure out
how to avoid cloning closures that are passed only to synchronous
loop-controller functions such as for() and not otherwise used
asynchronously.  Perhaps the signature of for() can make some
guarantees about not squirreling away the closure pointer in
some weird place.  This is perhaps related to the issue of timely
GC on pointers you know haven't been copied into outside storage.

Larry

Reply via email to