Re: getting rid of nested sub lexical problem
On Sat, 30 Dec 2000, Chris Nokleberg wrote: oooh, cool. I've added this to Apache::DB.xs: int stop_debugger() nice, i'll add that for the next version. It appears that setting PL_perldb to zero is all that's required to turn off the debugger! I thought I might have to fiddle with the symbol tables but this seems to work. yeah, that should do it. I've attached the latest version of Apache::NiceRegistry (suggestions welcome) below. Not sure this is the right thing to do , but I call Apache::DB::init_debugger directly because I need the return value (don't want to stop_debugger if it was turned on outside of this handler), and I don't want the warning that Apache::DB-init produces. calling init_debugger is fine. Also, why does Apache::DB unset $Apache::Registry::MarkLine? it was breaking Apache::SmallProf i think. it should local-ize that change at least.
Re: getting rid of nested sub lexical problem
On Thu, 21 Dec 2000, Doug MacEachern wrote: On Thu, 19 Oct 2000, Chris Nokleberg wrote: Following up on my post on this subject a couple of months ago, here is a proof-of-concept drop-in replacement for Apache::Registry that eliminates the "my() Scoped Variable in Nested Subroutine" problem. nice hack! It requires PERL5OPT = "-d" and PERL5DB = "sub DB::DB {}" environment variables set when starting the mod_perl-enabled httpd. This enables the %DB::sub hash table that holds subroutine start and end line info. I presume that this has some negative (marginal?) impact on performance. If someone knows of a better way to reliably figure out where a subroutine starts and ends, please let me know. there is quite a bit of overhead when -d is enabled. have a look at Apache::DB.xs, there's in init_debugger() function todo what -d does. if another method was added to turn it off, after the registry script was compiled, the overhead would be reduced a great deal. oooh, cool. I've added this to Apache::DB.xs: int stop_debugger() CODE: if (PL_perldb) { PL_perldb = 0; RETVAL = TRUE; } else RETVAL = FALSE; OUTPUT: RETVAL It appears that setting PL_perldb to zero is all that's required to turn off the debugger! I thought I might have to fiddle with the symbol tables but this seems to work. I've attached the latest version of Apache::NiceRegistry (suggestions welcome) below. Not sure this is the right thing to do , but I call Apache::DB::init_debugger directly because I need the return value (don't want to stop_debugger if it was turned on outside of this handler), and I don't want the warning that Apache::DB-init produces. Also, why does Apache::DB unset $Apache::Registry::MarkLine? Thanks, Chris -- package Apache::NiceRegistry; use base Apache::RegistryNG; use strict; use Apache::DB (); $Apache::Registry::MarkLine = 1; my %skip_subs = map { $_ = 1 } qw( handler BEGIN END CHECK INIT ); sub compile { my ($pr, $eval) = @_; $eval ||= $pr-{'sub'}; my $init_db = Apache::DB::init_debugger(); $pr-SUPER::compile($eval); Apache::DB::stop_debugger() if $init_db; my $package = $pr-namespace; my @lines = split /\n/, $$eval; foreach my $sub (grep /^$\Qpackage\E/, keys %DB::sub) { my ($name) = $sub =~ /:([^:]+)$/; next if $skip_subs{$name}; my ($start, $end) = $DB::sub{$sub} =~ /:(\d+)-(\d+)$/; $lines[$start + 1] =~ s:(sub[^\{]+\{):$1\{sub\{:; $lines[$end + 1] =~ s:\}(?!.*\})$:\}\}\}:; } $$eval = join "\n", @lines; $pr-flush_namespace($package); $pr-SUPER::compile($eval); } 1;
Re: getting rid of nested sub lexical problem
On Thu, 19 Oct 2000, Chris Nokleberg wrote: Following up on my post on this subject a couple of months ago, here is a proof-of-concept drop-in replacement for Apache::Registry that eliminates the "my() Scoped Variable in Nested Subroutine" problem. nice hack! It requires PERL5OPT = "-d" and PERL5DB = "sub DB::DB {}" environment variables set when starting the mod_perl-enabled httpd. This enables the %DB::sub hash table that holds subroutine start and end line info. I presume that this has some negative (marginal?) impact on performance. If someone knows of a better way to reliably figure out where a subroutine starts and ends, please let me know. there is quite a bit of overhead when -d is enabled. have a look at Apache::DB.xs, there's in init_debugger() function todo what -d does. if another method was added to turn it off, after the registry script was compiled, the overhead would be reduced a great deal.
RE: getting rid of nested sub lexical problem
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Wednesday, August 16, 2000 2:17 AM To: [EMAIL PROTECTED] Subject: getting rid of nested sub lexical problem Below is a processed version of the increment_counter example from the guide that works as expected. --Chris #!/usr/bin/perl -w use strict; for (1..3){ print "run: [time $_]\n"; run(); } sub run { my $counter = 0; increment_counter(); increment_counter(); sub increment_counter {{sub{ $counter++; print "Counter is equal to $counter !\n"; }}} } # end of sub run That gives me a 'Variable "$counter" may be unavailable at ./tst2 line 17.' warning. And its sort of obfuscated (to me, anyway). I'd probably do it this way: #!/usr/local/bin/perl -w use strict; #!/usr/bin/perl -w use strict; for (1..3){ print "run: [time $_]\n"; run(); } { my $counter; sub run { $counter = 0; print $counter,"\n"; increment_counter(); increment_counter(); } sub increment_counter { $counter++; print "Counter is equal to $counter !\n"; } }
Re: getting rid of nested sub lexical problem
"Douglas" == Douglas Wilson [EMAIL PROTECTED] writes: Douglas That gives me a 'Variable "$counter" may be unavailable at ./tst2 line 17.' Douglas warning. And its sort of obfuscated (to me, anyway). I'd probably do it this Douglas way: Douglas #!/usr/local/bin/perl -w Douglas use strict; Douglas #!/usr/bin/perl -w Douglas use strict; Douglas for (1..3){ Douglas print "run: [time $_]\n"; Douglas run(); Douglas } Douglas { Douglas my $counter; Douglas sub run { Douglas $counter = 0; Douglas print $counter,"\n"; Douglas increment_counter(); Douglas increment_counter(); Douglas } Douglas sub increment_counter { Douglas$counter++; Douglasprint "Counter is equal to $counter !\n"; Douglas } Douglas } But *that* won't work inside the big subroutine created by Apache::Registry (which is NOT the same as mod_perl, even though too many people think so :), and that was the original point. I'm not sure the new code fixes it. I think the problem is intractable, or equivalent to the Travelling Salesman and the Farmer's Daughter problem or something like that. :) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 [EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/ Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Re: getting rid of nested sub lexical problem
Converting "sub foo" into "local *foo = sub" won't work when the function is called before is declared, because the local only works for the rest of the block, not the entire block. i.e. you can't do foo(); local *foo = sub { ... }; Plus, I think you usually need the trailing semicolon anyway. --Chris On Wed, 16 Aug 2000, Dan Campbell wrote: [EMAIL PROTECTED] wrote: Due to forgetfulness I was recently bitten by the infamous "my() Scoped Variable in Nested Subroutines" problem using Apache::Registry, and it got me thinking about whether it is fixable. From the diagnostics: This problem can usually be solved by making the inner subroutine anonymous, using the sub {} syntax. When inner anonymous subs that reference variables in outer subroutines are called or referenced, they are automatically rebound to the current values of such variables. I think it should be possible for Registry to pre-process the source code to turn all top-level named subroutines into sub refs. For example, convert subroutines of the form sub foo { CODE } into sub foo { { sub { CODE } } } [snip] I think it would be easier to convert sub foo into local *foo = sub That way, you don't have to parse for the matching right brace. Something like: s/sub\s+(\w+)/local *\1 = sub/msg; # untested - just a guess might do the trick. -- Dan Campbell