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

Wise monks!

I implore your wisdom to dispel the shadows inside me. This is possibly the silliest question a hermit can post, so I also implore your patience as well. Ever since 2005 I have successfully opened files using the following (sinful) way:

open FILE, ">", $file;

Knowing that evil's way is easy and broad, and after repenting for my sins, I solemnly promised the @perl_deities that as far it is possible and reasonable I will stick to Damian Conway's Perl Best Practices ... and now I find myself banging my head against a wall, trying to understand why this works:

open (my $fh, ">", $file);

(program works as expected)

but this doesn't:

open (my $fh, ">", $file) or die "Can't open $fh";

"Global symbol "$fh" requires explicit package name (did you forget to declare "my $fh"?) at test.pl line 91. Execution of test.pl aborted due to compilation errors."

I am using warnings and strict pragmata as usual. Using perl 5.28.0 in Linux.

Any hint will be appreciated!

Replies are listed 'Best First'.
Re: open(), go away with bad way, or fail with the right way?
by LanX (Saint) on May 31, 2019 at 11:53 UTC
    You rather meant

     ... or die "Can't open $file"

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

      Of course! Thank you!

      Oh that was an embarrassing miss!

Re: open(), go away with bad way, or fail with the right way?
by Athanasius (Archbishop) on May 31, 2019 at 13:08 UTC

    Hello hda,

    LanX has answered your question, but I was somewhat surprised by the error message (which comes courtesy of use strict;, BTW), since it appears that $fh is already declared when the die code is parsed. Deparsing shows what’s going on: or is (apparently) rewritten as unless, which places the $fh in the die clause before its declaration in the call to open:

    22:56 >perl -MO=Deparse -Mstrict -we "my $file = 'x'; open (my $fh, '< +', $file) or die qq[Can't open $fh];" Global symbol "$fh" requires explicit package name (did you forget to +declare "my $fh"?) at -e line 1. -e had compilation errors. BEGIN { $^W = 1; } use strict; my $file = 'x'; die "Can't open ${'fh'}" unless open my $fh, '<', $file; 22:56 >

    Hope that’s of interest,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Perl makes "my" variables available in the statement after the "my". This allows things like

      my $foo = 'Bar'; my $foo = $foo x 2; say $foo; # 'BarBar'

      No, I do not defend this as a coding practice -- I'm just trying to elucidate how Perl works.

        "...This allows things like..."

        Yes and no:

        #!/usr/bin/env perl use strict; use warnings; use feature qw(say);; my $foo = 'Bar': my $foo = $foo x 2; say $foo; __END__

        Perl allows it generously but then it complains about  "my" variable $foo masks earlier declaration in same scope at ./foo.pl line 8..

        Iznogoud. But in a block it works flawless - no surprise:

        KARL : { my $foo = $foo x 2; say $foo; }

        But why the effort? You could say $foo x= 2; which results in BarBar. If this is what you wanted. What i assume.

        Best regards, Karl

        «The Crux of the Biscuit is the Apostrophe»

        perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

        It's pretty useful in nested scopes and closures.

        For instance

        my $level = $level + 1;

      Very Strange, But if it worked the way I expect, perl would not have found the error.
      Bill