Re: using a variable with require
by haukex (Archbishop) on Jun 22, 2022 at 06:36 UTC
|
See the core module Module::Load (there are others, like Module::Runtime, but this one is core), plus the \&{'subname'} symbolic reference syntax which is allowed even under strict. However, if $name is user input, this is still a security risk!
use warnings;
use strict;
use Module::Load qw/load/;
my $name = 'SomeModule';
load $name;
(\&{$name.'::somesub'})->();
| [reply] [d/l] [select] |
|
|
Hmmm ... from the doc, I would not have guessed it, but it appears that Module::Load is exactly what I need. Many thanks.
| [reply] |
Re: using a variable with require
by GrandFather (Saint) on Jun 22, 2022 at 04:23 UTC
|
A nasty solution to the invocation problem is to use eval. If SomeModule comes from the outside world this is a really bad solution!
use strict;
use warnings;
my $modName = 'Getopt::Long';
my $fixedMod = $modName;
$fixedMod =~ s!::!/!g;
$fixedMod .= '.pm';
require $fixedMod;
my $length = 24;
eval "${modName}::GetOptions('length:i' => \\\$length)";
However, there may be a much better solution to your big picture issue. What are you trying to do that seems to need a require?
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
| [reply] [d/l] |
|
|
Thanks. While I digest this suggestion, here's the big picture as requested.
I download podcasts from a number of sources. Each feed has its own peculiarities, requiring feed-specific coding, which I wish to isolate as modules. On the other hand, local processing is not feed-specific.
% download_processor feed1
% download_processor feed2
% ....
and there are modules feed1.pm, feed2.pm, and so on. What I would like to accomplish is when a new feed comes along, I just write a module for the new feed and don't have to modify the download_processor. | [reply] [d/l] |
|
|
use strict;
use warnings;
package FetchOne;
sub new {
my ($class, %params) = @_;
return bless\%params, $class;
}
sub type {
return 'Fetch type One';
}
package FetchTwo;
sub new {
my ($class, %params) = @_;
return bless\%params, $class;
}
sub type {
return 'Fetch type Two';
}
package main;
my $type = 'Two';
my $obj = "Fetch$type"->new();
print $obj->type();
Prints:
Fetch type Two
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
| [reply] [d/l] [select] |
|
|
The usual pattern for this is to put each implementation into a package hierarchy of objects, then know the package name you want to load, then:
use Module::Load;
...
load $package;
my $obj= $package->new( %options );
$obj->do_something;
No need for awkward cross-package function-calls. | [reply] [d/l] |
|
|
| [reply] |
|
|
geoffleach:
Your question already seems to be solved, but I thought I'd post a note with respect to your original problem and the use case you're describing here. The name of the file and the name of the package inside it isn't necessarily related. That's one of the difficulties that I expect Grandfather and others were thinking about.
So one thing you can do is use the same package name for all of your podcast processors. Then you can do something like:
$podcast_name = 'comedy_with_joe';
require "podcast_processors/${podcast_name}.pm";
PodcastProcessor::somesub();
where each of your podcast processor modules would look like:
# process podcasts for XYZ
package PodcastProcessor;
... yadda ...
sub somesub { ... }
...roboticus
When your only tool is a hammer, all problems look like your thumb. | [reply] [d/l] [select] |
Re: using a variable with require
by hippo (Archbishop) on Jun 22, 2022 at 08:41 UTC
|
Are you by chance trying to reinvent the Plugin wheel? If so, then why not just use (or take inspiration from) one of the Plugin architecture modules already available, eg. Plugin::Simple by stevieb.
If not, then it would likely be beneficial if you could elaborate on this apparent XY problem.
| [reply] |
|
|
It does appear that I have re-invented the Plugin wheel :-) Module::Load appears to satisfy my need.
| [reply] |
Re: using a variable with require
by GrandFather (Saint) on Jun 22, 2022 at 04:02 UTC
|
my $modName = 'Getopt/Long.pm';
require $modName;
Update Oops, this just answers the easy part of the question! Still thinking about the second part.
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
| [reply] [d/l] |
Re: using a variable with require
by Anonymous Monk on Jun 22, 2022 at 15:58 UTC
|
Another couple alternatives for executing a subroutine in a package determined at run time:
If it can be invoked as a static method, $name->somesub() will work.
In the general case, $name->can( 'somesub' )->() will also work. If you need to call somesub() more than once,
my $somesub = $name->can( 'somesub' );
$somesub->();
| [reply] [d/l] [select] |
Re: using a variable with require
by Anonymous Monk on Jan 24, 2023 at 00:32 UTC
|
require UNIVERSAL::require;
$name = 'SomeModule';
$name->require;
$name->somesub();
| [reply] [d/l] |
|
|
| [reply] [d/l] |