Skip Menu |

This queue is for tickets about the PadWalker CPAN distribution.

Report information
The Basics
Id: 21475
Status: rejected
Priority: 0/
Queue: PadWalker

People
Owner: robin [...] cpan.org
Requestors: whatever [...] davidnicol.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.0
Fixed in: (no value)



Subject: closed_over does not find "our" variables
perl -wle ' use PadWalker "closed_over"; my $f=33; our @o=(1..6); package w; sub j{print $f,@o}; package main; $r = closed_over(\&w::j); print "@{[%$r]}"; w::j' $f SCALAR(0x9ed2b40) 33123456 or better yet perl -wle 'package one; our $s=33; package two; $c = sub{$s = shift}; package thr; $two::c->("X"); print $one::s; use PadWalker "closed_over";print "@{[%{closed_over($two::c)}]}" ' X it seems clear from the above that our variables are included in closures too. How difficult would it be to include them in the return value of closed_over?
From: ROBIN [...] cpan.org
On Wed Sep 13 18:21:23 2006, DAVIDNICO wrote: Show quoted text
> it seems clear from the above that our variables are included > in closures too. How difficult would it be to include them > in the return value of closed_over?
It wouldn't be at all difficult. They aren't included because I couldn't think of a case where it would be useful to have them! I'll be happy to add this feature in some form, if you can convince me it's useful. Perhaps you could explain what you want to do with it. Robin
Subject: Re: [rt.cpan.org #21475] closed_over does not find "our" variables
Date: Thu, 14 Sep 2006 14:20:23 -0500
To: bug-PadWalker [...] rt.cpan.org
From: "David Nicol" <davidnico [...] cpan.org>
What I want to do is write a wrapper around B::Deparse::coderef2text that will properly resolve closures, so that $newcoderef = eval 'sub '.ImprovedCoderef2text($oldcoderef); will produce equivalent code in more circumstances. coderef2text greatly simplifies source code filtering by providing a standardized and more predictable syntax that raw perl code. In the specific case, I'm debugging a tailrecursion optimizer that rewrites "return(f(@args))" into "shift while @_; @_=@args; goto &f" and I would like it to not break due to lexical scoping issues. adding ourvars to the result of closed_over would be the easiest for _me_ but that clearly would not be backward-compatible in case someone is relying on closed_over leaving ourvars out. Listing them both, as is done with peek_*, would work as well. I'm busy and lazy and haven't cracked the source on PadWalker -- a "with" pragma that explicitly creates a pad loaded with the variables in a hash was one of my perl6 RFCs -- a comprehensive closed_over function (closed_over_all()?) -- the comprehensive closed_over would be able to provide a way to carry around a lexical environment for use with the hypothetical C<with> construct. If you have enough coffee in you to implement "with" while wearing your public service volunteer hero hacker hat, that would be really really cool from the point of view of my function rewriter, as I could just do something like use B::Deparse 'coderef2text'; my $deparse = B::Deparse->new(... flags go here); use PadWalker 1.1 qw/outer_lexicals/; #instead of "closed_over" sub CodeFilter { my ($cr,$filter) = @_; my $initialtext = $deparse->coderef2text($cr); my $lexicalenvironment = outer_lexicals($cr); my $filteredtext = $filter->($initialtext); dowith { return eval "sub $filteredtext" } $lexicalenvironment ; } instead of having to go through the filtered text and identify all symbols that exist as keys in %$lexicalenvironment and replace each with a hash lookup expression, which is what I'm currently considering. Could outer_lexicals present lexicals that are not actually captured? I have been under the impression that closures defer destruction of the whole lexical environment, but that may have been addressed. On 9/14/06, via RT <bug-PadWalker@rt.cpan.org> wrote: Show quoted text
> > <URL: http://rt.cpan.org/Ticket/Display.html?id=21475 > > > On Wed Sep 13 18:21:23 2006, DAVIDNICO wrote:
> > it seems clear from the above that our variables are included > > in closures too. How difficult would it be to include them > > in the return value of closed_over?
> > It wouldn't be at all difficult. They aren't included because I couldn't > think of a case where it would be useful to have them! > > I'll be happy to add this feature in some form, if you can convince me > it's useful. Perhaps you could explain what you want to do with it. > > Robin
-- Although efforts are under way to mitigate the problem, this message may contain flippancy, hyperbole and/or confusing assertions. Please reply directly to fall2006sigfile@davidnicol.com for clarification of any points appearing unclear, vague, cruel, frustrating, threatening, negative, dilletantish or otherwise unprofessional before taking action based on misintepretation or misconstruction of such points.
Thanks for your detailed and thoughtful reply. Lots of interesting ideas here! The reason I didn't think it was useful to capture the 'our' variables is that our declarations have no run-time effect: they only affect the compilation. This means that they can't be "closed over" in any meaningful sense. For example, the following two snippets produce *identical* opcodes for sub foo (assuming we're in the main package): # example 1 our $foo; sub foo { $foo } # example 2 sub foo { $::foo } The real problem is that B::Deparse will deparse this as sub foo { $foo } which is not compilable under 'strict vars'. So even if I did add a method to PadWalker that lets you determine the our variables, and you wrote your code to take advantage of it, you would still find that example 2 would deparse to code that didn't compile. Therefore I think that the correct solution to this problem is to change B::Deparse to fully-qualify variable names when 'strict vars' is in effect. I thought it already did this, to be honest, but it doesn't seem to. (I haven't tried it with the latest bleadperl though. Have you?) [Incidentally, closures only capture the lexicals that are actually referenced in the sub. It's therefore possible to achieve surprising effects by referring to outer lexicals from an eval-string.] Your dowith idea is very interesting. It would actually have to be evalwith, I think, because the pad needs to exist at compile time. I've never tried to fake up a pad out of whole cloth like that, but it ought to be possible. If I did it, it would be a separate module rather than part of PadWalker. I can see how that would be useful for the kind of thing you're trying to do. Thanks for the suggestion; I'll let you know if I get anywhere with it. Robin