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

Simple question, but this is really puzzling me. Why does this work?

use strict; use warnings; open my $fh, "somefile"; my $sc = *$fh{IO}; print <$sc>;

I thought the *FOO{THING} syntax only worked with package variables.

Replies are listed 'Best First'.
Re: *FOO{THING} syntax used on a lexical variable
by tilly (Archbishop) on Jun 12, 2005 at 07:02 UTC
    The trick is that the *FOO{THING} syntax works on typeglobs. Package variables are in typeglobs. But typeglobs need not be package variables.

    My comment might make more sense if you go back to how we did that with Perl 5.005.

    use strict; use warnings; my $fh = do {local *FOO}; open $fh, "somefile"; my $sc = *$fh{IO}; print <$sc>;
    Is it less surprising now?
      *FOO{THING} syntax works on typeglobs

      Ah, that's what I was missing. I knew there was a simple explanation! Thanks for your reply. For further reinforcement of your point:

      $ perl -le 'open my $fh, "file"; print $fh;' GLOB(0x814cc20)

      And to show some symmetry with the package variable variety of typeglob:

      open FOO, "file"; print ref \*FOO; # prints GLOB open my $fh, "file"; print ref \*$fh; # prints GLOB
Re: *FOO{THING} syntax used on a lexical variable
by ysth (Canon) on Jun 12, 2005 at 07:53 UTC
    After the open, $fh is a reference to an IO handle (the thing that goes in the IO slot of a glob). If you use an IO ref as if it were a glob ref, it automatically gets a new glob wrapped around it, because on a perl language level there isn't any other way to deal with it.
    $ perl -wle'$x = *STDOUT{IO}; print for $x, map \*$x, 1..10' IO::Handle=IO(0x10164ce0) GLOB(0x10141190) GLOB(0x101412f8) GLOB(0x10167d4c) GLOB(0x10167d70) GLOB(0x10167d94) GLOB(0x101410ac) GLOB(0x10167e54) GLOB(0x10167e78) GLOB(0x10167e9c) GLOB(0x10167ec0)
      After the open, $fh is a reference to an IO handle (the thing that goes in the IO slot of a glob).
      No, it's a GLOB ref.
        Er, yeah, well...so it is.
        my $sc = <fh>;

        print $sc;