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

Such as:
use strict; { package Foo; our $str = 'foo str'; } { package Bar; our $str = 'bar str'; } my $class = 'Foo'; # access Foo::str using soft ref my $value; { no strict 'refs'; my $soft = $class.'::str'; $value = $$soft; } # So, how to get $Foo::Str without soft ref?
Moreover, how to know whether an arbitrary package has a specific global?
  • Comment on How to access globals in arbitrary classes, without using soft ref?
  • Download Code

Replies are listed 'Best First'.
Re: How to access globals in arbitrary classes, without using soft ref?
by moritz (Cardinal) on Feb 22, 2010 at 08:53 UTC
    The symbol table is a hash, so you can check existence with exists. See perlmod for a description of symbol tables.
    use strict; use warnings; use 5.010; { package Foo; our $bar; } { if (exists $::{'Foo::'}{bar}) { say "There's a Foo::bar with some sigil"; } if (exists $::{'Foo::'}{baz}) { say "There's a Foo::baz with some sigil"; } }

    (Update: added code)

      thanks a lot!

        They are called symbolic refs.

        I must disagree with moritz. Using %:: instead of symbolic refs does not help at all. All the same problems and disadvantages exist because it does exactly the same thing. Using %:: has the additional disadvantage that it's not caught by use strict 'refs';. In fact, it's generally less readable and harder to code using %:: instead of symbolic refs, so it's usually a step backwards to use %::.

        If you want to improve your approach, use accessors.

        use strict; { package Foo; my $str = 'foo str'; sub str { my $class = shift; $str = $_[0] if @_; return $str; } } { package Bar; my $str = 'bar str'; sub str { my $class = shift; $str = $_[0] if @_; return $str; } } my $class = 'Foo'; my $value = $class->str();
Re: How to access globals in arbitrary classes, without using soft ref?
by shmem (Chancellor) on Feb 22, 2010 at 19:44 UTC
    # So, how to get $Foo::Str without soft ref?
    Moreover, how to know whether an arbitrary package has a specific global

    1. various ways.
    a) Any symbol table your current symbol table knows about - is in the current symbol table. So:

    use strict; package Foo; use vars qw($str); # $Foo::str created $str = 'foo str'; package main; my $pack = "Foo::"; my $var = "str"; print ${*{${$main::{$pack}}{$var}}{SCALAR}}; __END__ foo str

    b) You could also use string eval - but that's as deprecated as symbolic references hereabouts ;-)

    use strict; $Foo::str = 'foo str'; my $class = 'Foo'; my $value = eval "\$$class\::str"; print $value,$/;

    2. Look into the symbol table:

    package Foo; use vars qw($str); $str = "foo str"; package main; my $pack = "Foo::"; my $var = "str"; print "$_: ",(defined ${$main::{$pack}}{$_} ? 'yup' : 'nope'),$/ for qw(str bar); __END__ str: yup bar: nope

    update: Caveats about autovivification apply. You might want to break up the lookup into steps, operating with defined. Consider:

    $\=$/; use strict; use warnings; package Foo; use vars qw($str); $str = "foo str"; package main; my $pack = "Bar::"; my $var = "str"; print "yup" if defined ${$main::{$pack}}{$var}; /::$/ and print for keys %main:: __END__ version:: Tie:: utf8:: re:: CORE:: DynaLoader:: mro:: strict:: attributes:: Bar:: <----here Regexp:: vars:: UNIVERSAL:: Foo:: main:: Carp:: PerlIO:: IO:: Internals:: warnings:: DB::

    Symbol tables are subject to autovivification, too.

Re: How to access globals in arbitrary classes, without using soft ref?
by JavaFan (Canon) on Feb 22, 2010 at 11:14 UTC
    So, how to get $Foo::Str without soft ref?
    An answer has already been given. But what's against using a soft reference in this case?