Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Conditional loading of methods

by bruno (Friar)
on Dec 09, 2008 at 04:18 UTC ( [id://729074]=perlquestion: print w/replies, xml ) Need Help??

bruno has asked for the wisdom of the Perl Monks concerning the following question:

Oh monks,

Here's the issue. I need to load a method conditionally, the condition being that a certain module Foo::Bar is usable. So after asking in the chatterbox, the following snippet arose:

eval "use Foo::Bar"; unless ($@) { sub my_method { # Code } }

So far so good. It worked for a trivial test subroutine, but not for my real-life example. The thing is, Foo::Bar = PDL. And PDL adds a lot of new syntax. Now, the eval expression is being executed at runtime, but the  my_method block has its syntax checked at compile time. So by the time that the syntax of the my_method is checked, PDL hasn't been loaded yet, and the module gives a syntax fatal error when the sub tries to

$matrix(0,0) = $value;
which is perfectly legal if PDL is loaded.
Also, I can't use  eval { use Foo::Bar }, because it dies on me if Foo::Bar isn't present.

I might be missing something here, but I surely don't know how to solve this. I would really appreciate some enlightenment!

Replies are listed 'Best First'.
Re: Conditional loading of methods
by Tanktalus (Canon) on Dec 09, 2008 at 06:17 UTC

    I'd suggest a similar trick to what we do in C/C++ when the wrapped library is too large to individually load each function. Cheat.

    package Wrap::PDL; use PDL; use base 'Exporter'; # for simplicity... sub my_method { # Code } 1;
    And then, in your module, just do something like this:
    my $has_PDL = eval "use Wrap::PDL qw(my_method); 1"; #... if ($has_PDL) { my_method(0, 0, $value); }
    Well, either that, or just require PDL to be installed :-P

    Update: Fletch pointed out that I had $has_PDL in double-quotes and needed either backwhacking or to be in single-quotes. So I removed it altogether. This method takes advantage of tye's trick on ensuring whether an eval executes properly or not by checking its return code rather than $@, and ensuring that correct execution actually does result in a true value. I can also be more confident in using lexical variables here. I'm pretty sure eval STR can use lexicals declared outside of its scope, but here I don't even have to think about that.

    Another alternative would be:

    my $has_PDL = eval { require Wrap::PDL; Wrap::PDL->import(qw(my_method)); 1; }
    which is probably better in that I prefer using eval BLOCK over eval STRING whenever possible.
Re: Conditional loading of methods
by jasonk (Parson) on Dec 09, 2008 at 04:33 UTC

    The only way you are going to get around the syntax problems is to only compile the code in question if the module exists....

    eval "use Foo::Bar"; eval <<"END" unless $@; sub my_method { # Code } END

    but because that is going to introduce it's own problems, I would opt for moving that code into a module or a library...

    eval "use Foo::Bar"; if ( $@ ) { require "have-foo-bar-library.pl"; } else { require "dont-have-foo-bar-library.pl"; }

    As for the second part, because you are using eval BLOCK rather than eval STRING, the use will still be evaluated at compile time, rather than at run time. You could get the effect you are looking for by breaking the use up into it's components though...

    eval { require Foo::Bar; import Foo::Bar; }

    www.jasonkohles.com
    We're not surrounded, we're in a target-rich environment!
Re: Conditional loading of methods
by etj (Deacon) on Jun 06, 2022 at 00:08 UTC
    I think that trying to conditionally have non-standard-Perl syntax conditionally is likely to be a bad idea. PDL::NiceSlice continues to be the gift that keeps on being a maintenance burden out of all proportion with its utilitygiving (though it is genuinely an interesting idea).

    My recommendation for this situation would be to use the conventional slice method, and possibly (as also suggested) to move the conditional stuff in any case to a separate module.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://729074]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2024-04-23 14:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found