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

Reply via email to