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