On Fri, Jul 11, 2008 at 10:04:54PM -0400, Bob Rogers wrote: > Absolutely, but that's not where the problem lies. The problem is that > r28763 did so implicitly and unconditionally, overwriting anything > newclosure might have done. If you meant "have its outer_ctx set > I<explicitly> whenever an outer sub is invoked", then I apologize; I > misunderstood you. (And in any case, it was rude to have honked.)
Let's see if I can make myself as clear as I can: * I'm not at all trying to defend r28763 as being correct. Never have been. * In [1] I'm agreeing that capturing the lexical environment at the time of closure invocation is wrong. Phrased another way: In [1] I _think_ I'm completely agreeing that autoclosures (capture at point of closure invocation) is bad, and we should eliminate them. I guess I should've made this more explicit. * What I suggested instead in [1] is that we capture the lexical environment for the closure when its *outer sub* is invoked. (This is not at all what r28763 does -- r28763 captures the closure's lexical environment when the *closure* is invoked, which I agree is wrong.) * I don't see that it matters significantly if the automatic capture for closures occurs explicitly (by PIR statements placed at the beginning of the outer sub) or implicitly (by Parrot when the closure's outer sub is invoked). The second would be much more efficient if it can be done, and would alleviate the need for the compiler to generate the explicit calls, but as I said in [1], I'm willing to go with the explicit version if need be. [1] http://rt.perl.org/rt3/Ticket/Display.html?id=56398#txn-442254 > In the attached example, I think the lines > > my $recur = sub { > > my $subthing = shift; > > dump_thing($subthing, $prefix.' '); > > }; > guarantee that $recur gets a distinct closure for each level > of call, since a closure is cloned upon assignment. > > Yes; this was intended as an example where "autoclose" clearly does not > work. Since I thought I had already stipulated that autoclose doesn't work, I didn't understand the point of the example. > But I must confess that I still don't understand what it means not to > "clone" a closure. What is an "uncloned closure" anyway? Will @Larry > deign to speak? Instead of trying to answer "What is an uncloned closure", I'll try answering "What is a cloned closure?" Based on my understanding of things after figuring out the approach in [1], every closure gets a capture from its outer sub, but we clone those closures that we may need to return or reference in another context. Cloning occurs whenever a closure is used in an rvalue context (but isn't being immediately invoked). > Let me try to clarify: The only reason I mentioned stuffing closures > back into the symbol table was to show that "autoclose" is not > necessary. (I failed, though, because Patrick correctly pointed out > that "autoclose" is currently required for methods, with or without the > "multi-", though I consider it a bug that you *have* to autoclose in > these cases; I'm not convinced that can always be made to work.) I think the approach I gave in [1] means we never have to autoclose (again assuming autoclose means "capture at point of closure invocation"). > IMHO, it does not make any sense to do newclosure on a MultiSub; I > cannot imagine what that might mean. Jonathan gave me the answer on IRC earlier tonight. Again, let's consider "newclosure" as being a combination "capture + clone" operation. Performing capture on a MultiSub simply means that we loop through all of the elements of the MultiSub and perform a capture on any of its individual closures where the outer_sub matches the thing invoking the capture (since capture can only be performed from a closure's outer sub). Perform a clone on a MultiSub simply clones the MultiSub, which by virtue of the 'capture' operation on the MultiSub will have already had all of the relevant closures set to the appropriate outer context. To summarize: 1. AFAICT, after [1] I've completely come around to the idea that performing a capture upon closure invocation (autoclose) is bad 2. We should provide a 'capture' operation that can be performed at the beginning of any outer sub invocation to immediately bind any closures specifying the current sub as :outer to the current lexical environment. 3. Whenever a closure is to be returned or stored such that it may be invoked from somewhere other than its outer context, we simply clone it. (The closure will already have the correct lexical environment by virtue of having performed #2 above.) Pm