First, the test (rearranged to include only the relevant parts):

+.sub main :main
+    .local string ok, not_ok
+    ok = "ok"
+    not_ok = "not ok"
+    
+    # if 'not ok' is printed, it means that the lexical environment
+    # for the first closure in each pair, (where "out" = "ok")
+    # was overwritten by the lexical environment created for the
+    # second closure (where "out" = "not ok")
+    
+    $P10 = makebar_clone(ok)
+    $P20 = makebar_clone(not_ok)
+    $P10()
+.end
+
+.sub makebar_clone
+    .param pmc out
+    .lex 'out', out
+    .const .Sub s = 'bar'
+    $P0 = clone s
+    .return($P0)
+.end
+
+.sub bar :outer(makebar_clone)
+    $P0 = find_lex 'out'
+    say $P0
+.end

(This prints "not ok". The test in the patch expects "ok".)

You're arguing that the different copies of "bar" that are returned from 
makebar_clone 
should have different lexical environments. I'm pretty sure that this is not 
the case. Without 
using "newclosure", there's no closure so the lexical environments are the same.

What the :outer does in this case is rearrange the lexical stack so that 
"makebar_clone" 
appears in the lexical stack for "bar". So we're using the lexical environment 
from the last 
time that "makebar_clone" was called. It's bizarre that this even works because 
without the 
closure, I'd think that the lexical environment would have destroyed.

I'm not sure how intentional this is. The PDD isn't clear (to me) about what 
:outer means in 
the absence of "newclosure". I'd definitely be interested in seeing why this 
would be a useful 
feature. More detail in the PDD would be nice.

Thanks for the interesting patch.

--
Matt Diephouse


Reply via email to