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

Dear Monks,

Please examine the following code. I am trying to use a type glob to access values in a hash.

use strict; use warnings; use 5.010; my %h = qw{a 1 b 2}; my @h = (100, 200, 300); my $h = 10; say $h{a}; say $h[0]; say $h; my $href = *h{HASH}; my %hash = %{$href}; say $hash{a}; --output:-- 1 100 10 No type glob foo for you!*
* Can't use an undefined value as a HASH reference at 1perl.pl line 14.

How can I use a type glob to get at the hash's values?

Thank you.

Replies are listed 'Best First'.
Re: type glob
by ikegami (Patriarch) on Nov 17, 2009 at 07:17 UTC

    Can't use an undefined value as a HASH reference

    You're trying to reach a variable via a type glob in the symbol table, yet the variable in question isn't in the symbol table. It's a lexical (my) variable.

    How can I use a type glob to get at the hash's values?

    Implicitly, if the glob is in the symbol table:

    my %h1 = qw{a 1 b 2}; *h2 = \%h1; # Create and initialise glob print %h2, "\n"; # Access hash referenced by glob

    Explicitly, if the glob is in the symbol table:

    my %h1 = qw{a 1 b 2}; *h2 = \%h1; # Create and initialise glob print %{*h2}, "\n"; # Access hash referenced by glob

    Indirectly, if the glob is in the symbol table:

    my %h1 = qw{a 1 b 2}; my $glob = *h2; # Create glob *$glob = \%h1; # Initialise glob print %$glob, "\n"; # Access hash referenced by glob

    Indirectly, if the glob is outside the symbol table:

    sub new_glob { return local *X } my %h = qw{a 1 b 2}; my $glob = new_glob(); # Create glob *$glob = \%h; # Initialise glob print %$glob, "\n"; # Access hash referenced by glob

    I am trying to use a type glob to access values in a hash.

    Why?

      Hi, thanks for the response.

      I am trying to use a type glob to access values in a hash.

      Why?

      I read about them in the docs, and I wanted to try them out.

      You're trying to reach a variable via a type glob in the symbol table, yet the variable in question isn't in the symbol table. It's a lexical (my) variable.

      Hmm...things aren't as straight forward as I was led to believe. Ok, I did some reading about symbol tables, and if I understand them correctly, they are just hashes that contain the variables in your program. The keys in the hash are the variable's names and the values are the variable's values. However, the docs say that the symbol table hash does not contain "my" variables--only dynamic variables. What is a dynamic variable? Anything that isn't a my variable?

      Well, if we are always told to use 'my' to declare variables, how does a program create "dynamic variables"?

      I discovered this "solution" to my original question:

      #use strict; #use warnings; use 5.010; %h = qw{a 1 b 2}; @h = (100, 200, 300); $h = 10; say $h{a}; say $h[0]; say $h; my $href = *h{HASH}; my %hash = %{$href}; say $hash{a}; --output:-- 1 100 10 1

      I have a question about this code:

      my %h1 = qw{a 1 b 2}; *h2 = \%h1;

      How is that different from doing this:

      my $href = \%h1;

      Is h2 one of those dynamic variables?

      say *h2; --output:-- main::h2

      Hey, it's in the hash table. Oh boy, I'm on a roll:

      say $main::h2{a}; --output:-- 1

        However, the docs say that the symbol table hash does not contain "my" variables--only dynamic variables.

        Let's forget that name and call them "package variables", please.

        What is a package variable? Anything that isn't a my variable?

        No, Perl also has anonymous variables. A package variable has the form

        $Foo::Bar::moo

        This can be abbreviated to

        $moo

        in some circumstances.

        Well, if we are always told to use 'my' to declare variables, how does a program create package variables?

        You seem to be missing the point. Don't use package variables. Always use lexical variables.

        Ok, I did some reading about symbol tables, and if I understand them correctly, they are just hashes that contain the variables in your program. The keys in the hash are the variable's names and the values are the variable's values. However, the docs say that the symbol table hash does not contain "my" variables--only dynamic variables. What is a dynamic variable? Anything that isn't a my variable?

        The place that I'd look for documentation on the symbol table is Symbol Tables, but I don't see any use of the term ‘dynamic variables’ there (and I wouldn't expect to see one in the Perl documentation; it's not a standard term). Did you look somewhere else?

        Variables in Perl are either local *, in which case they are lexically scoped, or global, in which case they are dynamically scoped. It is global (or, better, ‘package’) variables that you will find in the stash. Lexicals are created with my, as you say; globals are created with our, or, if you are naughty and don't use strict, implicitly whenever you reference a previously un-declared variable.

        UPDATE: Sorry, I was very very slow (had to go to class in the middle) and ikegami gave a (slightly more admonitory :-) ) reply first.

        * Except that we call them lexicals, not locals, because they have nothing to do with the variables referenced (not created) by local.

      The following is what I was trying to test out with my first program:

      use strict; use warnings; use 5.010; my %h = qw{a 1 b 2}; my @h = (100, 200, 300); my $h = 10; *all = \%h; *all = \@h; *all = \$h; #<overwriting that strange variable??> say ${*all}{a}; say ${*all}[0]; say ${*all}; --output:-- 1 100 10

      It demonstrates that a type glob has "slots" for each perl type that can be assigned to the same variable name, in this case a hash, an array, and a scalar. There are also slots for subroutines, etc. Then when you dereference the glob, which has many references stored in it, the glob dereferences the correct reference based on the context. In the example, the first dereference involves a hash subscript, {a}, so the glob chooses the hash reference and dereferences that. The second dereference involves an array subscript, [0], so the glob dereferences the array reference, etc. Glob is smart.

      No news to you, obviously. :)

        Just out of curiosity, I ran your script with B::Deparse. That's what I love about Perl---there's always more than one way to do it:-):

        #!/usr/bin/perl sub BEGIN { use warnings; use strict 'refs'; require 5.01; } use warnings; use strict 'refs'; BEGIN { $^H{'feature_say'} = q(1); $^H{'feature_state'} = q(1); $^H{'feature_switch'} = q(1); } my (%h) = ( 'a', '1', 'b', '2' ); my (@h) = ( 100, 200, 300 ); my $h = 10; *all = \%h; *all = \@h; *all = \$h; say ${ *all; }{'a'}; say ${ *all; }[0]; say ${ *all; };