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

Let's pretend there is no 'f1.txt' file in the current directory and there exists f2.txt one.

Following script: (use strict; is always on)

open my $fh, "<f1.txt" or do { print STDERR "can't open <f1.txt, but nevermind, I'll try f2.txt\n +"; open $fh, "<f2.txt" or die "still can't..."; }; print <$fh>; # this gives a warning "read on closed filehandle";
Last print statement is in a problem: even if f2.txt exists, I see the mentioned warning, but why wasn't failure at nearby open statement ??
If we're seeing different $fh-s, why this was not caught by use strict?

Things work different if I move declaration of $fh above:

my $fh; open $fh, "<f1.txt" or do { print STDERR "can't open <f1.txt, but nevermind, I'll try f2.txt\n +"; open $fh, "<f2.txt" or die "still can't..."; }; print <$fh>; # I see the content of f2.txt here ...
How this strange scoping explained?

In my currently non-enlightened view, DWIMery is broken.
Can anyone restore DWIMery, please? :)

Replies are listed 'Best First'.
Re: "my $filehandle" scoping strange problem
by Fletch (Bishop) on Apr 14, 2006 at 12:33 UTC

    B::Deparse is your friend in strange syntax corners.

    $ perl -MO=Deparse,-p,-q # . . . your first example here ^D unless (open(my $fh, '<f1.txt')) { do { print(STDERR "can't open <f1.txt, but nevermind, I'll try f2.t +xt\n"); (open($fh, '<f2.txt') or die(q[still can't...])); }; } print(<$fh>);

    So you can see now that $fh is scoped to the unless block that's been implicitly created.

    Update: Not that that's not a little wierd, mind you. After looking at it a second time it's slightly surprising.

      Given, as you said, $fh is scoped to the unless block, why the almighty DWIMery allows to use $fh afterwards within a scope of use strict;??

        It doesn't. Add a -Mstrict or use strict; and it complains.

        $ perl -MO=Deparse,-p,-q use strict; open my $fh, "<f1.txt" or do { print STDERR "can't open <f1.txt, but nevermind, I'll try f2.txt\n +"; open $fh, "<f2.txt" or die "still can't..."; }; print <$fh>; ^D Global symbol "$fh" requires explicit package name at - line 5. - had compilation errors. use strict 'refs'; unless (open(my $fh, '<f1.txt')) { do { print(STDERR "can't open <f1.txt, but nevermind, I'll try f2.t +xt\n"); (open(${'fh'}, '<f2.txt') or die(q[still can't...])); }; } print(<$fh>);