Search code examples
perlsubroutineglobal

Can I define a subroutine that can be called like a built-in, everywhere?


Currently, during debugging, I tend to insert

carp Dumper \@foo, \%bar;

statements into my code, and regularly run into the problem that Carp and Data::Dumper are not imported in the current package. To avoid this problem, I defined the following sub in a central file that's always included:

sub main::bla {
    use Carp; use Data::Dumper;
    carp Dumper @_;
}

So now I can do

main::bla \@foo, \%bar;

everywhere, but the main:: annoys me. Is there something like a global package that's always imported, in any package, automatically (just like built-ins practically are imported everywhere)?


Solution

  • You could just call it

    ::bla( \@foo, \%bar );
    

    In earlier days, I used to put util functions in a Ut package. And that was fine, but I noticed that my code wasn't really as modular as I thought of it. Each module that depended on Ut functions being there could only succeed if somebody took the trouble to build that namespace.

    In the end, I considered use and require statements as simply documenting dependencies. There are more flexible ways to change what code is called by library modules, rather than changing their implementation in main.

    For example, you could do this in a single use statement.

    use Ut blah => sub { 
        use Carp; 
        use Data::Dumper;
        carp Dumper @_;
    };
    

    And define the import:

    sub import { 
        shift; # It's just me
        my ( $name, $impl ) = @_;
        if ( $name eq 'blah' && ref( $impl ) eq 'CODE' ) { 
            *blah = $_[1];
        }
        ...
    }
    

    I still use the ut pattern, when I'm developing a lot of code at once. But I don't mind writing

    ut:dump_var( $var )
    

    as opposed to saving 3-4 characters (because sometimes I call it U::).

    Now, it appears that you don't want to do this long term, and dumping out your variables is a useful thing for development. If you really want to do this, Smart::Comments does it like so:

    ### @foo
    ### %bar
    

    All it takes is one use statement.

    use Smart::Comments;