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

Hi I need to write a generic subroutine which takes a variable name and looks at it's caller's package to see if that variable is defined and if it's defined, returns it's value. Since this is a library route, I cannot say 'use PackageA' etc in the package where this routine resides - since the library routine might get called from a number of other packages which are unknown at the compile time. Any ideas?
  • Comment on examining other package's variable without 'use'

Replies are listed 'Best First'.
Re: examining other package's variable without 'use'
by hardburn (Abbot) on May 09, 2003 at 17:57 UTC

    You want the caller() builtin:

    my ($package, $filename, $line) = caller; print "It's there!\n" if defined ${$package}::variable;

    Actually, I'm not sure if you can access the varible like that, but it should get you started.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Re: examining other package's variable without 'use'
by pfaut (Priest) on May 09, 2003 at 17:55 UTC

    Why not have the caller pass the variable instead of it's name? Why call a subroutine to get the value of a variable that's already accessible? Perhaps you meant to look in the caller's caller's namespace? This sounds like a broken design to me.

    90% of every Perl application is already written.
    dragonchild
Re: examining other package's variable without 'use'
by broquaint (Abbot) on May 09, 2003 at 18:39 UTC
    a generic subroutine which takes a variable name and looks at it's caller's package to see if that variable is defined and if it's defined, returns it's value
    Something like this should do (also complies with strictures too).
    sub isdef { my($var, $pkg) = ( shift, scalar(caller)."::" ); return unless defined $main::{$pkg}; return unless defined $main::{$pkg}{$var}; return unless defined *{ $main::{$pkg}{$var} }{SCALAR}; return ${ *{ $main::{$pkg}{$var} }{SCALAR} }; }
    Note, this will only work with scalar value types.
    HTH

    _________
    broquaint

Re: examining other package's variable without 'use'
by Abigail-II (Bishop) on May 09, 2003 at 21:50 UTC
    Define an import sub, and use caller in the import sub to find which package called you. Given the package name, you can access the variable, once you turn off strictness.

    Note that your programming style is widely regarded as bad style. Some maintainance programmer will come along, see the assignment to the special variable in the calling package, without seeing the variable used, and she will delete the assignment. The program will then mysteriously break. This is using global variables in one of the worst ways imaginable. You should consider either passing the data to the used package when doing the use statement, or by setting a variable in the used package.

    Abigail

      On a tangent, that's exactly why Exporter's interface sucks. That it's well documented and widely known does not make it any better.

      Makeshifts last the longest.

Re: examining other package's variable without 'use'
by dws (Chancellor) on May 09, 2003 at 17:56 UTC
    cannot say 'use PackageA' etc in the package where this routine resides - since the library routine might get called from a number of other packages which are unknown at the compile time.

    The usual idiom for pulling in a package at runtime is

    eval { require $package }; die "$@" if $@;
    perldoc -f require will give you more information.

    I misread the question. hardburn gives a good answer below.