Q on "use"

K

kj

I have the following short script:


use strict;

my $services;
my @packages = qw(Foo Bar Baz);

for my $package (@packages) {
my @services;

eval <<EOEVAL;
use $package;
\@services = $package\::get_available_services;
EOEVAL

$services->{ "http://acmeServices.com/#${_}" } = $package
for @services;
}

use SOAP::Transport::HTTP;

SOAP::Transport::HTTP::CGI
->dispatch_with( $services )
->handle();


The for-loop cycles over a list of packages, all of which implement
the sub get_available_services(), and uses eval to "use" each
package, and call the package's get_available_services.

As far as I can tell this code does the right thing, but I find
the construct with the eval rather klugey. Is there a better way
to achieve the same effect?

Thanks!

kj
 
M

Martien Verbruggen

use strict;
my @packages = qw(Foo Bar Baz);

for my $package (@packages) {
my @services;

eval <<EOEVAL;
use $package;
\@services = $package\::get_available_services;
EOEVAL
[snip]

The for-loop cycles over a list of packages, all of which implement
the sub get_available_services(), and uses eval to "use" each
package, and call the package's get_available_services.

As far as I can tell this code does the right thing, but I find
the construct with the eval rather klugey. Is there a better way
to achieve the same effect?

What exactly do you think is kludgy? The string eval?

You could replace the C<use> with C<require>, possibly followed by
C<import>, but due to the "magic" that is involved, you would still
need a string eval.

You could C<use> the packages earlier, if you're not trying to catch
possible errors with this eval, and only do the
get_available_services() calls here, but it'd still require string
evals, or a list of C<use> statements.

C<use> and C<require> only do their magic with barewords, and to get
those barewords at runtime, you need string eval.

Maybe Module::Load, or Module::Runtime, available from CPAN can get
rid of some of the kludgy feel. Or maybe you can just wrap that eval
string away in a subroutine somewhere, to make the code look less
kludgy. But, in effect, I am pretty certain you need a string eval at
some point. Or you might need to do something that feels even more
horrible: for example you could change the module notation (with ::)
to a path name (with your local path separator), and use require.

Martien
 
B

Ben Morrow

Quoth (e-mail address removed):
horrible: for example you could change the module notation (with ::)
to a path name (with your local path separator), and use require.

I believe / works on all platforms (certainly, %INC uses / as the separator on
all platforms).

Ben
 
K

kj

In said:
On Tue, 4 May 2004 01:19:48 +0000 (UTC),
use strict;
my @packages = qw(Foo Bar Baz);

for my $package (@packages) {
my @services;

eval <<EOEVAL;
use $package;
\@services = $package\::get_available_services;
EOEVAL
The for-loop cycles over a list of packages, all of which implement
the sub get_available_services(), and uses eval to "use" each
package, and call the package's get_available_services.

As far as I can tell this code does the right thing, but I find
the construct with the eval rather klugey. Is there a better way
to achieve the same effect?
What exactly do you think is kludgy? The string eval?

Yes. (It's very subjective, I know...) I had hoped that I could
have used something like "no strict refs", but I can't get that to
work...

BTW, I should have specified that, in the real application I'm
working on, the packages in @packages are known only at run time.
That's why I have to do the eval song-and-dance.

Thanks for your comments,

kj
 
H

Heinrich Mislik

Assuming that your package names have no :: and that your sub
get_available_services doesn't take any parameters, the following should work (untested):

use strict;

my $services;
my @packages = qw(Foo Bar Baz);

for my $package (@packages) {
my @services;
require "$package.pm";
@services = $package->get_available_services;

$services->{ "http://acmeServices.com/#${_}" } = $package
for @services;
}
 
K

kj

In said:
Assuming that your package names have no :: and that your sub
get_available_services doesn't take any parameters, the following
should work (untested):
use strict;

my $services;
my @packages = qw(Foo Bar Baz);

for my $package (@packages) {
my @services;
require "$package.pm";
@services = $package->get_available_services;

OK, I like that.

But just to be clear, regarding your caveat about '::' in the
package names, is there anything wrong (apart from aesthetics,
maybe) with:

for my $package (@packages) {
my @services;
(my $package_filename = "$package.pm") =~ s,::,/,g;
require $package_filename;
@services = $package->get_available_services;

# etc. ...
?

Thanks!

kj

P.S. If there's a better way than the regexp above to go from a
package name to the corresponding file name (assuming the usual
naming convention), please let me know.
 
B

Brian McCauley

kj said:
But just to be clear, regarding your caveat about '::' in the
package names, is there anything wrong (apart from aesthetics,
maybe) with:

for my $package (@packages) {
my @services;
(my $package_filename = "$package.pm") =~ s,::,/,g;
require $package_filename;
@services = $package->get_available_services;

# etc. ...

No, there is nothing wrong with that apart from aesthetics. One of
the things I find most aesthetically displeasing is the premature
declaration of @services.
P.S. If there's a better way than the regexp above to go from a
package name to the corresponding file name (assuming the usual
naming convention), please let me know.

You may want to consider UNIVERSAL::require.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,150
Messages
2,570,853
Members
47,394
Latest member
Olekdev

Latest Threads

Top