Re: Controlling "use" statements
by doom (Deacon) on Jun 13, 2007 at 17:28 UTC
|
Yes, but you don't want to use "use" to do it, because it acts at compile time (it has an implicit BEGIN wrapped around it already). On the other hand requre acts at runtime, which means it can be used to conditionally load modules as needed. If you want it to behave like use, though, you also need to call import on the module, right after doing a require.
There's a gotcha to require semantics though, it requires a "bareword", which is fine if you want to do
something like this:
if ($DEBUG) {
require Data::Dumper;
import Data::Dumper;
}
But if you want to put the module names in variables,
then you'll probably need something like this:
my @debug_modules = qw( Data::Dumper CGI Test::Deep );
foreach my $mod (@debug_modules) {
eval "require $mod";
import $mod;
}
(Note, some folks are down on eval STRING, but this is a case where it's necessary.)
If you want to read up on this, look into things like "perlmod", and the "use" and "require" sections of "perlfunc". Do not however, waste your time looking for "import" in perlfunc. It's not a "function", it's more like a reserved name for a subroutine. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Thank you, this is very useful. As a followup, what would be the correct way to include certain features with the module?
For example, I want the equivalent of
use CGI::Carp qw(fatalsToBrowser set_message)
I know that
require CGI::Carp qw(...)
won't work, because it can only handle barewords. What is the correct way to do this?
Thanks.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
use CGI::Carp qw(fatalsToBrowser set_message)
is a shortcut for
BEGIN {
require CGI::Carp;
import CGI::Carp qw(fatalsToBrowser set_message);
}
You can easily add an if in there.
BEGIN {
if ($DEBUG) {
require CGI::Carp;
import CGI::Carp qw(fatalsToBrowser set_message);
}
}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
BEGIN {
use vars qw($devel);
$devel = 0; # production
}
BEGIN {
my @args = $devel ? qw(fatalsToBrowser set_message) : ();
require CGI::Carp;
CGI::Carp->import(@args);
}
The equivalent of use Module LIST is BEGIN { require Module; Module->import(LIST) }.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Do not however, waste your time looking for "import" in perlfunc. It's not a "function", it's more like a reserved name for a subroutine.
But there is a perlfunc entry for it, just in case you do look.
| [reply] [Watch: Dir/Any] |
Re: Controlling "use" statements
by almut (Canon) on Jun 13, 2007 at 17:27 UTC
|
You could use the module if, e.g.
BEGIN { our $DEBUG = 1 }
use if $DEBUG, Data::Dumper;
# ...
or
BEGIN { sub DEBUG {1} }
use if DEBUG, Data::Dumper;
# ...
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
There's one problem with if: There's no equivalent to use Module ();.
The conditional version of use Module; is use if $cond, 'Module';
The conditional version of use Module LIST; is use if $cond, Module => LIST;
However, use if $cond, Module => (); is the same as use if $cond, 'Module';
Furtunlately, this doesn't seem to be a concern for the OP.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
That's right. If you desperately needed that functionality, you
could patch if.pm as shown below. (In case you'd rather not mess
with the system version, just create a copy in some local lib directory
and make that directory be searched before the system ones.)
You could then for example write
use if $DEBUG, 'Data::Dumper' => undef;
to import nothing, just like with
use Data::Dumper ();
As the module is actually rather short, here is the full code:
package if;
sub work {
my $method = shift() ? 'import' : 'unimport';
die "Too few arguments to `use if' (some code returning an empty lis
+t in list context?)"
unless @_ >= 2;
return unless shift; # CONDITION
my $p = $_[0]; # PACKAGE
(my $file = "$p.pm") =~ s!::!/!g;
require $file; # Works even if $_[0] is a keyword (like open)
return if @_==2 && !defined $_[1]; # <--- ADDED
my $m = $p->can($method);
goto &$m if $m;
}
sub import { shift; unshift @_, 1; goto &work }
sub unimport { shift; unshift @_, 0; goto &work }
1;
When being passed undef, the line marked with "<--- ADDED"
would make the sub return before executing the real import() of the target
module via goto &$m (where $m is referring to import in this case).
(Not well tested! &mdash use at your own risk...)
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Controlling "use" statements
by ikegami (Patriarch) on Jun 13, 2007 at 17:57 UTC
|
People are suggesting solutions. Let me identify the problem:
BEGIN {
# These will only be used in the
# debugging version.
if ($DEBUG) {
use strict;
use warnings;
use Data::Dumper;
use CGI::Carp;
}
# These are needed by the program
# regardless.
use CGI::Minimal;
use HTML::Template;
# ... others, etc.
}
Like BEGIN blocks, use statements execute as soon as they are compiled. Your use CGI::Carp; executes as soon as it is compiled, with no regard to whether that code is reached at run-time. That means the if ($DEBUG) has no bearing on whether use statements inside the if are executed or not.
Secondly, strict and warnings are pragmas. They only affect the lexical block in which they are located (and nested blocks). use strict; would only work for the body of the if.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
No, the pragmas are controllable with use and no, e.g.
use strict;
$MyClass::foo = 'boink';
sub bar {
no strict; # strict turned off for this sub
}
... # strict again in effect
They live in files which are imported, like modules - but they act like switches and turn on and off certain flags at compile time, for their lexical scope.
There's no reason to turn strict or warnings off for a "working" version, once the "development" versions behave with them. Again: *no* *reason*. And in case you ask again - no, there is no reason, period.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
my $DEBUG;
BEGIN { $DEBUG = $ARGV[0]; }
use if $DEBUG, 'strict';
# <-- The compiler is here because
# Perl executes use statements
# as soon as it compiles them.
# "strict" will work until the
# end of this block (namely
# until the end of the file).
print($test); # strict error if $DEBUG
The following works:
my $DEBUG;
BEGIN {
$DEBUG = $ARGV[0];
if ($DEBUG) {
require strict;
import strict;
}
}
# <-- The compiler is here because
# Perl executes BEGIN blocks
# as soon as it compiles them.
# "strict" will work until the
# end of this block (namely
# until the end of the file).
print($test); # strict error if $DEBUG
The point, however, is that the following doesn't work:
my $DEBUG;
BEGIN {
$DEBUG = $ARGV[0];
if ($DEBUG) {
eval <<'__EOI__';
use strict;
# <-- The compiler instance used
# by eval is here because
# Perl executes use statements
# as soon as it compiles them.
# "strict" will work until the
# end of this block (namely
# until the end of the code
# passed to eval).
__EOI__
}
}
print($test); # No strict error
Actually, I thought the second one wouldn't work either, but it does for the reason I gave in the comments.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Controlling "use" statements
by adrianh (Chancellor) on Jun 14, 2007 at 12:47 UTC
|
use strict;
use warnings;
Please reconsider disabling these in your live version. The difference in load/run time is trivial and I can pretty much guarantee that you'll wish you had warnings on at some point on the runtime box :-)
| [reply] [Watch: Dir/Any] [d/l] |