From: "Patrick R. Michaud" <[EMAIL PROTECTED]> Date: Fri, 11 Jul 2008 21:55:41 -0500
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. Understood; you have been clear on that. * 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. I did take that point (eventually, any way). * 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.) Yes, and yes. * 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). It may matter if code that doesn't want implicit capturing can't turn it off. I can do that now by always doing an explicit "newclosure" and never using the "template" continuations. Now that you bring it up, I can't see that the consequence of implicit capture would be any worse than holding on to the garbage that an otherwise-collectable context would reference. But that would be a significant consequence to the Lisp community. 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. By "explicit" I also include adding pragmas to the inner subs, which would still enable implicit capturing in C. I am interested in this because it would allow a way to turn implicit capturing *off* simply by ignoring it, as well as to enable it selectively. > 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. The example was a direct response to what you said here: However, I'd still like the capability to give an existing Closure an outer_ctx without having to replace it in the symbol table, method table, or MultiSub PMC . . . For some reason, I interpreted that as being equivalent to autoclose, and therefore just as risky. But this is foolish; if the compiler decides it is correct, then who am I to disagree? So I apologize for wasting time (yours and Jonathan's) with this 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). This gets back to a question I asked earlier in this thread: What is the difference between the clone and the original? They capture the same context, and they refer to the same code, so they ought to be indistinguishable. Is it to prevent morphing? > 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"). As long as the *compiler* has full control of where and how closures are captured, then I am in full agreement. 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 Great; I think we have achieved closure. Sorry for being dense (and for stealing your pun). -- Bob [1] http://rt.perl.org/rt3/Ticket/Display.html?id=56398#txn-442254