in reply to Making it clearer to say that a sub is defined within current package

Edit: a disclaimer first. I think there is some theorical interest in the question, but it's actual realization is not risk-free (either because it somehow bypasses strictures, or because of performance, if not both). That's the main reason why I don't provide a full working example (also because I'm lazy, and my laziness is very happy with that first excuse :P).

It's complicated. Basically, it's because perl lets you scope those variables dynamically but nor lexically. Or, in simpler English, you can tell how long you want a name to exist, but not where. For example if DWIM() made all the local function available in my::, and unDWIM the reverse you would have:

package MySelf; my $var='Hello'; sub world { 'World' }; DWIM(); my::world(); # Calls the World function from this package NotMe::planet(); # Sees my::world but not $var unDWIM();
planet() from NotMe would not be able to access $var, but would be able to call my::world(). And, if there already was a world() function inside NotMe, calling my::world inside NotMe::planet() would call MySelf::world() instead of NotMe::world() as expected...

I see two (and a half) workarounds for this issue:

1) You can have a copy of each function in the current package with a name pattern that does what you want. Eg, add my__ before every local function. For example you'd declare: sub world { 'World' }; and call it as my__world from inside your package. Technically that second name would still be available to outside modules as MySelf::my__world, but you could just decide to never call my__ functions with a package prefix (or die by checking if caller is different from the current package). The my__ functions could either be created from the list of @EXPORTs, or by using AUTOLOAD to create the alias *{"my__$function"} = \&$function when you need it.

2) Also using AUTOLOAD, you can have a package My; so that when you call My::anyFunction from a package, it would look inside the calling package for "anyFunction" and call it if it exists.

Although the two AUTOLOADsolutions look more convenient, they would be tricked by imported functions. So if you import Data::Dumper into MySelf, my__Dumper or My::Dumper would both call Data::Dumper::Dumper as if it had been defined inside MySelf. So I suppose the better solution would be to create an alias for every function that you export?

There also the alternative of doing it the other way around: never importing function in the current package, for example:

package MySelf; package Ext { use Data::Dumper; use Text::CSV qw( csv ); }; Ext::Dumper(Ext::csv(in => "data.csv"));
The issue with that one is that you would be able to call Ext::csv from any other package, even if it doesn't have the matching use in its file.

Replies are listed 'Best First'.
Re^2: Making it clearer to say that a sub is defined within current package
by LanX (Saint) on Apr 11, 2019 at 15:32 UTC
    > My::Dumper() would both call Data::Dumper::Dumper()

    It's definitely possible to tell in which package a sub was declared.

    I saw it in the book perlhacks and IIRC it's available in B

    The problem I see is that My:: is global, you would need the hint hash to restrict it's effect only to the file importing My.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Well that's an issue if you want to set *My::Dumper = *Data::Dumper::Dumper once and for all. But if the only function defined in my is My::AUTOLOAD, and it always checks the calling package you should be fine wouldn't you? (At execution time at least, you'd lose compilation time errors with My::function() instead of function())

        In a clean design you don't want My:: to have effect outside the scope using it.

        Also probably a lowercase name my:: for pragma would be more appropriate to avoid a clash with cpan modules.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      > It's definitely possible to tell in which package a sub was declared.

      From Sub::Info

      my $cobj = B::svref_2object($sub); my $name = $cobj->GV->NAME; my $file = $cobj->FILE; my $package = $cobj->GV->STASH->NAME;

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice