Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Getting module to call importer's function

by jredburn (Sexton)
on Sep 22, 2004 at 20:56 UTC ( [id://393046]=perlquestion: print w/replies, xml ) Need Help??

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

I would like to have a module with exported functions (there may be a class-based solution to this problem which I'd be very open to, as well) that has a number of different scripts which use it. So say we have a module M with an exported function x. What I'd like is to be able to call x in a script S with use M;. So we execute M::x. I'd like to define x something like this:
sub x { return unless &_x; ...; &_x; }
where _x is a function in S. Is this possible? Right now it looks for _x in M, which is not where it is, obviously. I would like to have M have no knowledge of the various scripts that will end up using it.

Replies are listed 'Best First'.
Re: Getting module to call importer's function
by ikegami (Patriarch) on Sep 22, 2004 at 21:05 UTC

    Like this?

    sub x { my $func = do { no strict 'refs'; *{caller() . '::_x'}{CODE} }; die() unless defined $func; &$func; # or &$func(...); }

    Test code:

Re: Getting module to call importer's function
by etcshadow (Priest) on Sep 22, 2004 at 21:06 UTC
    I think that:
    sub x { my $package = caller; return unless UNIVERSAL::can($package, "_x"); ... eval "${package}::_x"; die $@ if $@; }
    Is what you're looking for.
    ------------ :Wq Not an editor command: Wq

      That's potentially too smart by half.

      sub x { my $package = caller(); my $sub = $package->can( '_x' ); return unless defined $sub; $sub->( @_ ); }
Re: Getting module to call importer's function
by BrowserUk (Patriarch) on Sep 22, 2004 at 21:26 UTC

    Why not just pass a reference to the callback sub?

    package M; use strict; require Exporter; our @ISA = qw[ Exporter ]; our @EXPORT = qw[ x ]; sub x{ my( $sub ) = @_; &$sub; } 1;
    #! perl -slw use strict; use M; sub _x{ print __PACKAGE__ . "_x() called" } x( \&_x ); __END__ P:\test>393046 main_x() called

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      The problem is that I'm calling x from an external library so I don't have that freedom. You guys got me on the right track though, thanks much!
Re: Getting module to call importer's function
by fglock (Vicar) on Sep 22, 2004 at 21:12 UTC

    How about:

    use strict; package M; sub x { my $caller_package = shift; print "Caller: $caller_package\n"; $caller_package->_x(); } package main; sub _x { my $class = shift; print "$class _x\n"; } main->M::x();

    output:

    Caller: main main _x

    update: added "shift" in _x - thanks ikegami.

      Note: The above has the side effect of passing an extra argument to _x. Probably acceptable.
        Yep, got this working. Is there a way to call the function in a different context so as not to have to stick a dinky shift; at the start of _x? I'm trying some of the other discussed options, but can't get them working with passing parameters to _x.
Re: Getting module to call importer's function
by borisz (Canon) on Sep 22, 2004 at 21:05 UTC
    Update:
    Ups, I misunderstand the question. The other answers are much better.
    Yes, use the Exporter module to export functions in your namespace. perldoc Exporter
    Boris

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-24 05:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found