Re: Redefining Imported Subs: of scope and no
by LanX (Saint) on Feb 09, 2013 at 02:22 UTC
|
Long read!
(wont try it again! ;-)
I don't understand why you're using feature qw(say) if you wanna redefine 'say.
This makes say() a builtin which has to be overridden like described in perlsub#Overriding Built in Functions.
Otherwise this works:
$verbose=0;
sub not_say {
print 'not saying';
}
sub say {
print @_,"\n";
}
{
no warnings;
*say = \¬_say if not $verbose;
}
say 'test';
or even simpler:
use strict;
use warnings;
no feature "say";
sub say {
print "nothing";
}
say 'test';
OTOH you will certainly have problems if someone manages to globally switch say on.
My suggestion is to replace say() with something like 'log()' or 'out()' and keep it simple, don't redefine the sub at all, just put the test condition into the function body.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Redefining Imported Subs: of scope and no
by BrowserUk (Patriarch) on Feb 09, 2013 at 10:43 UTC
|
I don't normally repond to threads I frontpage -- I usually only front page stuff I don't know the answer to -- but as it seems that all you have so far are responses confirming what you already discovered.
Having just re-read your post, I'm no longer sure that you are asking what I originally thought you were asking. Or rather, I see that you could be asking for one of 3 different things:
- The easiest way of shutting up your debug statements (using say), in this script, without fully deleting them.
Perhaps the simplest way would be to tie stdout and make the say method do nothing.
- Or, you might be asking a more generic question of how to have debug statements that you can turn on & off with a simple boolean.
In that case, you might consider looking at Smart::Comments.
- Or, the crux of your question might be: how to override feature enabled built-ins.
In which case, perhaps Devel::Pragma is a starting point.
Perhaps if you make it clear whichever of those -- or whatever other -- objective is your primary goal, maybe you'll get more helpful responses.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [Watch: Dir/Any] |
Re: Redefining Imported Subs: of scope and no
by 7stud (Deacon) on Feb 09, 2013 at 04:26 UTC
|
I don't understand why you're using feature qw(say) if you wanna redefine 'say.
I had trouble understanding that too. But as I understand it, the op turned on say() with his use statement, and now the op has say() statements littered throughout the code. Now the op wants to figure out a way to make his say() statements print nothing if a switch is set. Note that his custom say() sub doesn't print anything if $verbose is false.
As for 'use if', I was looking at that too, and I found two problems with it:
- 'use if' doesn't work as advertised for me. Here is the syntax shown in the 'if' pragma:
use if CONDITION, MODULE => ARGUMENTS
…but it doesn't work for me:
use if $/ = "\n", 5.012 => qw( say );
--output:--
Can't locate 5.012.pm in @INC (@INC contains: /Users/7stud/perl5/perlb
+rew/perls/perl-5.16.0/lib/site_perl/5.16.0/darwin-2level /Users/7stud
+/perl5/perlbrew/perls/perl-5.16.0/lib/site_perl/5.16.0 /Users/7stud/p
+erl5/perlbrew/perls/perl-5.16.0/lib/5.16.0/darwin-2level /Users/7stud
+/perl5/perlbrew/perls/perl-5.16.0/lib/5.16.0 .) at /Users/7stud/perl5
+/perlbrew/perls/perl-5.16.0/lib/5.16.0/if.pm line 13.
BEGIN failed--compilation aborted at 2.pl line 1.
Yet all my perl programs use 5.012 without error. In addition, the 'use if' can't see a my variable in the code, e.g.
my $verbose = 1;
Apparently, 'use if' can only see a global variable that exists at compile time. Using our to declare $verbose doesn't work either:
our $verbose = 1;
use if $verbose, 'strict';
$v = 'hello';
No error. I see that you got around that problem with use constant.
- Turning off say() will cause all the say() statements in the op's code to produce errors.
It looks like 'use subs' can be made to work (I think you originally posted something about that??):
use strict;
use warnings;
#use 5.012; #enables say()
use subs qw( say );
my $verbose = 1;
sub say {
if ($verbose) {
print shift, " world\n";
}
}
say 'hello';
--output:--
hello world
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
but it doesn't work for me:
Not surprising, $/="\n" assignment is always true (and assignment ), 5.12 is not a module (maybe you wants features), and 5.12 doesn't export say (features you want, maybe)
Apparently, 'use if' can only see a global variable that exists at compile time.
nothing specific to if, that is the nature of compile-time and our/my, initialization doesn't happen until later
use constant DEBUG => !!( 0 || $ENV{PERL_DEBUG_MYAPPNAME} );
use if DEBUG , qw' Carp::Always ';
| [reply] [Watch: Dir/Any] |
Re: Redefining Imported Subs: of scope and no
by aitap (Curate) on Feb 09, 2013 at 07:09 UTC
|
| [reply] [Watch: Dir/Any] [d/l] |
Re: Redefining Imported Subs: of scope and no
by LanX (Saint) on Feb 09, 2013 at 03:16 UTC
|
> Unfortunately I can't have say something like no feature say unless $verbose;, can't use or no in conditional or anything like that.
maybe use feature is special, but normally use if should do that.
update
works for me:
use strict;
use warnings;
use constant VERBOSE=>0;
use if VERBOSE, feature => "say";
sub say {
print "nothing";
}
say 'test';
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Redefining Imported Subs: of scope and no
by 7stud (Deacon) on Feb 09, 2013 at 05:50 UTC
|
use feature 'say';
undef &say;
*say = \¬_say;
say 'test';
sub not_say {
print 'not saying';
}
Maybe I'm getting my namespaces all mixed up because that doesn't seem to redefine the sub at all.
The confounding thing is that this works:
use strict;
use warnings;
use 5.012;
#Rule: sub names are entered into the symbol table.
sub abc {
print "abc\n";
}
sub xyz {
print "xyz\n";
}
local *abc; #gets rid of 'redefined main::abc' warning'
*abc = \&xyz;
abc;
--output:--
xyz
But this doesn't work:
use strict;
use warnings;
use 5.012;
sub xyz {
print "xyz\n";
}
local *say;
*say = \&xyz;
say 'hello';
--output:--
hello
Nor does this:
use strict;
use warnings;
use 5.012;
use subs qw( say ); #Supposedly overrides a built in
my $verbose = 1;
sub say {
if ($verbose) {
print shift, " world\n";
}
}
say 'hello';
--output:--
hello
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Redefining Imported Subs: of scope and no
by 7stud (Deacon) on Feb 09, 2013 at 04:50 UTC
|
use strict;
use warnings;
no feature "say";
sub say {
print "nothing";
}
say 'test';
Edit--Hey, that doesn't work! Where's the ability to flip the real say() back on? | [reply] [Watch: Dir/Any] [d/l] |
|
You're confusing me!
Why do you always seem to ask me if you reply to someone else?
Please don't be surprised if I'm not replying.
And please don't simply change your posts after being proofed wrong in a reply.
> Where's the ability to flip the real say() back on?
Just swap no with use!
feature should be scoped (in this example file scoped), which makes much sense when debugging!
Otherwise the OP could (like already shown) do "use if" for testing a global constant like main::VERBOSE spreading all files.
Anyway manipulating say for debugging purpose is such a broken idea that I don't wanna invest more into this discussion... :)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
Re: Redefining Imported Subs: of scope and no
by ikegami (Patriarch) on Feb 11, 2013 at 06:10 UTC
|
How do I dynamically redefine imported subroutines?
That's actually quite easy, but say is not being imported; it's not even a subroutine! say is an operator, and use feature 'say'; merely controls whether the compiler recognises it or not. (It always recognises CORE::say, though.)
Some operators can be overridden from within Perl by overriding GLOBAL::CORE::op, and some can't. The following checks whether say can be overridden this way:
>perl -E"say defined(prototype('CORE::say')) ?'yes':'no'"
no
Its funky syntax doesn't permit it.
say
say LIST
say FILEHANDLE LIST
say BLOCK LIST
It could be done using a CallChecker, but that involves dropping to C/XS.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
lanx@nc10-ubuntu:~$ perl -e 'CORE::say("bla")'
CORE::say is not a keyword at -e line 1.
lanx@nc10-ubuntu:~$ perl -E 'CORE::say("bla")'
bla
lanx@nc10-ubuntu:~$ perl -version
This is perl, v5.10.0 built for i486-linux-gnu-thread-multi
> say is an operator, and use feature say; merely ...
As a minor nitpick, according to the definitions in perlglossary I'd rather use built-in and not operator to describe say, though the differences are indeed fuzzy.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Not always, at least for me, with which version did you check?
It apparently went missing until 5.16.
As a minor nitpick, according to the definitions in perlglossary I'd rather use built-in and not operator to describe say, though the differences are indeed fuzzy.
Builtin functions are a slight superset of what both perlop and perlfunc call list operators and named unary operators. say is a builtin because say is a list operator. (It's fuzzy which builtins aren't operators.)
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Redefining Imported Subs: of scope and no
by 7stud (Deacon) on Feb 09, 2013 at 17:45 UTC
|
Not surprising, $/="\n" assignment is always true
Ack!
5.12 is not a module (maybe you wants features)
I didn't know that. From the use docs:
use VERSION also enables all features available in the requested version as defined by the feature pragma,
In any case, like the op I'm wondering where the name 'say' is stored? It is not in main's symbol table:
use strict;
use warnings;
use 5.012;
our $x;
use Data::Dumper;
say Dumper($main::{x}); #%main:: is the name of the symbol table
say Dumper($main::{say});
say Dumper($main::{print});
--output:--
$VAR1 = *::x; #typeglob for 'x', in package ::(shorthand for main::)
$VAR1 = undef;
$VAR1 = undef;
So it appears that the name 'say' might be in the same place as the name 'print', i.e. not in the main:: symbol table. But then why doesn't 'use subs' succeed in redefining say()? Then again, I can't redefine print() with 'use subs' either:
use strict;
use warnings;
use 5.012;
use subs qw( print );
sub print {
printf "%s %s\n", shift, 'world';
}
print 'hello';
--output:--
hello
I am able to redefine the chdir() builtin:
use strict;
use warnings;
use 5.012;
use Data::Dumper;
say Dumper($main::{chdir});
--output:--
$VAR1 = undef;
use strict;
use warnings;
use 5.012;
use subs qw( chdir );
sub chdir {
printf "%s %s\n", shift, 'world';
}
chdir 'hello';
--output:--
hello world
It appears that some builtins are more builtin than others.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
...
Hit the reply link, the reply link, the link that says reply to reply to the post you want to reply to , that is the link you're supposed to click to have threaded discussion, otherwise it is not theaded discussion but a flat list, flat lists are not effective for following a conversation, that is why the twitts and other "chats" use the @username stuff, so click the reply link and its like this isn't some chat and not flat at all...
As to your question, CORE is CORE::, many threads about CORE::, ex::override
perl -e " CORE::say 1 ; "
perl -e " CORE::say 1 ; say 2 "
perl -E " CORE::say 1 ; say 2 "
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
Say::Compat - Backwards compatibility wrapper for say()
| [reply] [Watch: Dir/Any] |
Re: Redefining Imported Subs: of scope and no
by Dallaylaen (Chaplain) on Feb 11, 2013 at 13:46 UTC
|
Don't mess with say, it will byte you or a later maintainer of this code.
Instead, (1) define sub debug {...}; with a plain old if inside. (2) Replace all occurences of say with debug(). (3) Replace those say's that aren't really for debugging back again. (4) Re-run your tests to see if anything got lost.
You can then consider moving debug() to a separate module for re-use, or switch to Log4perl altogether as other monk suggests here, or even write a debug_off() sub that replaces debug() on the fly. But at least it's not like "Hey, say() prints nothing! Our perl interpreter must be broken!"
| [reply] [Watch: Dir/Any] |
Re: Redefining Imported Subs: of scope and no
by temporal (Pilgrim) on Feb 11, 2013 at 16:40 UTC
|
Whoa, had no idea that this would spark such a lively discussion. Excellent.
I had intended to use say as an example - but it turned out to be the problem, huh? Ha! Go figure.
LanX - did not know about use if, so that's a neat plus. Hopefully you haven't quite yet learned your lesson about reading and replying to my ridiculously long posts ♥
Also comforting is that most of my solutions will work with normal non-CORE:: namespace imports.
As for all the advice in regards to how I ran into this question - debug output style/best practices and such - in the future I'll be going with aitap's great suggestion: Log::Log4perl. Very flexible and feature-rich, thanks for the tip!
BrowserUk, after diving the rabbit hole of replies, my question is/was/will be where do these definitions reside and how do I get at them? Not so much how to get around a silly design decision I made =D As usual, thanks for pointing me towards some great reading material. I'll definitely be playing around with Devel::Pragma to investigate any future questions in this vein.
So here we go:
- say lives in CORE::, where it can (usually) be accessed
- See ex::override for overriding CORE:: functions.
- use feature 'say' enables say as an operator - which means that once created it cannot be redefined.
- use if works, but has some constraints concerning order of your sub and verbosity definitions.
- Using say for debugging is silly - but educational!
Thanks to all of you for the great replies and entertaining repartee ;)
Strange things are afoot at the Circle-K.
| [reply] [Watch: Dir/Any] [d/l] [select] |