[Chicago-talk] calling functions in a package by its name
Steven Lembark
lembark at wrkhors.com
Mon Jan 21 13:01:59 PST 2008
>>> my $prog = "use $classname;";
>>> eval $prog; die("eval '$prog' failed with " . $@ ) if ($@);
>> You do have to use string eval to load the class. require is better
>> than use here, though. (Do you want $class->import to be called? Not
>> for classes, usually.)
>
> OK, I'll give eval "require.." a try. It definitely should not import things into the caller's
> namespace - this thing is basically just an object factory.
Actually, the "import" sub might be used to
initialize some portion of the module itself
at runtime, e.g.,
use Benchmark qw( :hireswallclock );
turns on the high-res wallclock feature in
Benchmark. If you only use require then it
may help to add something like:
if( $package->can( 'import' ) )
{
log_a_warning "Ignoring import in: $package";
}
or
if( $package->can( 'import' ) )
{
$package->import;
}
>> How about:
>>
>> my $class = 'Foo';
>> eval "require $class";
>> $class->can('new')->(); # Foo->new()
>
> I'll give that a try.
Note: foo->can(x)->() breaks if the package
doesn't have a new coderef in their namespace
(you'll be dispatching an undef). With minimal
boilerplate this becomes a lot easeir to debug:
if( my $sub = $class->can( 'new' ) )
{
# "$class->$sub" gets you to the same place,
# this avoids the indirect-object form and
# makes it a bit more obvious that you exect
# $sub to be a coderef.
$sub->( $class );
}
else
{
confess "Package missing 'new': $class"
}
It's also trivial to have the class return its
value of $constructor, which allows for a more
general:
my $constructor = $classdata->{ constructor } || 'new';
if( my $sub = $class->can( $constructor ) )
{
...
}
else
{
confess "Bogus class: $class cannot $constructor"
}
> few stringy evals from the production code today.
Always a good thing :-)
--
Steven Lembark +1 888 359 3508
Workhorse Computing 85-09 90th St
lembark at wrkhors.com Woodhaven, NY 11421
More information about the Chicago-talk
mailing list