Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Flexibility in Module for Import or Execute

by temporal (Pilgrim)
on Mar 11, 2013 at 21:17 UTC ( #1022875=perlquestion: print w/replies, xml ) Need Help??
temporal has asked for the wisdom of the Perl Monks concerning the following question:

Hey again monks,

I run up against this design decision a lot and figured I'd better ask for some wisdom before continuing with what feels like a bit of an odd workaround.


# perl -w package test_caller; if (caller) { print 'imported'; return 1; } else { print 'direct execution'; } print ' do not need to end in truth'; 0; # 'direct execution do not need to end in truth'


#! perl -w use test_caller; # 'imported'

This works fine. For a little I was mixed up between exit codes and module import return value. I need to explicitly return 1; in order to make sure that the module stops execution there for importers and returns truth. For some reason I was laboring under the misconception that use checks the exit code when in fact it only cares about the return value.

I am aware that implementing this sort of thing isn't entirely sane. Best practice dictates that I keep module and script functionality separate. But I end up with a lot of scripts that turn into modules because they have lots of useful code for other scripts. But I'd like to keep the ability to run these module-ified scripts standalone.

Anyway, relying on caller feels a little bit hacky. So I'm looking for opinions/advice/admonishment regarding a better way to distinguish between a module being executed directly versus being imported?

Replies are listed 'Best First'.
Re: Flexibility in Module for Import or Execute
by tobyink (Abbot) on Mar 11, 2013 at 21:41 UTC

    You could check if $0 matches __FILE__, but $0 is not a read-only variable, so it's possible that some module you've used has changed it.

    Or you could use the core Perl function designed for this kind of thing... caller.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Flexibility in Module for Import or Execute
by dsheroh (Prior) on Mar 12, 2013 at 10:10 UTC
Re: Flexibility in Module for Import or Execute
by temporal (Pilgrim) on Mar 13, 2013 at 15:11 UTC

    Well, if this is the sort of thing that caller was designed for then I'm happy to continue doing what I'm doing. Just never know when there's some useful-but-hidden little convenience built into Perl so I thought I'd ask. Thanks for the affirmation tobyink.

    At least I now have something to call these code monstrosities thanks to dsheroh. Actually, they're not all that bad - I like how brian d foy refers to them as 'doing double duty' as a module and a script; that's how I view them. His method of implementing this functionality is definitely more elegant:

    __PACKAGE__->run( @ARGV ) unless caller(); # use the __PACKAGE__ symbol to call the appropriately scoped run()

    He then illustrates that double duty these Modulinos are capable of pulling is by allowing submodules to inherit and optionally override the parent subroutines. So if you're into creating object oriented inheritance hierarchy styled code there is definitely some benefit to be had here.

    Personally, my design ends up with one 'master' Modulino which is used by some number of other scripts. This master Modulino contains all common code plus some optional initialization routines and shared variables via Exporter. I'll usually run it directly for tasks composed entirely of its subroutines.

    Strange things are afoot at the Circle-K.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1022875]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2017-09-20 05:09 GMT
Find Nodes?
    Voting Booth?
    During the recent solar eclipse, I:

    Results (231 votes). Check out past polls.