in reply to Beware of global! And bless the local!

G'day alexander_lunev,

A lesson well learned — thanks for posting.

"But why would anyone write about it again, and again, and again?"

I wouldn't be concerned with that. I've certainly urged people to use local in many posts; and not just for $/ but for other special variables which can have a global effect.

I actually take this a step further and use an anonymous block along the lines of

{ open my $fh, ... local $/; # do whatever with $fh here }

From the local documentation:

"A local modifies the listed variables to be local to the enclosing block, ..."

And from "perlvar: Variables related to filehandles":

"Usually when a variable is localized you want to make sure that this change affects the shortest scope possible."

Also note that the "= undef" is unnecessary; and the "close $fh" is implicit at the end of the anonymous block (see open for details). I'm not saying don't use them: just advising that they're optional (at least in the type of code you show in your example).

— Ken

Replies are listed 'Best First'.
Re^2: Beware of global! And bless the local!
by alexander_lunev (Pilgrim) on Dec 12, 2019 at 13:26 UTC

    Hello, kcott!

    I should adopt anonymous blocks as a every-day programming technique, thank you. As with the simple but powerful Truth of local, it's also always under my nose, and still I'm not using it - but I will!

    As for unnecessary things like "= undef" and "close $fh" - I like it this way, it's more informative and illustrative this way. It takes more chars to write, but less mind time-clocks to comprehend the meaning. I like to write explicit "return $string;" instead of laconic "$string" in the end of the sub. I think that a programming language should stay language that we speak and understand, and I don't want to short-cut to the point in expense of explanation. In the end I'm speaking this language with myself-in-the-future, and it's for me I write those many words that could be omitted.

      "I should adopt anonymous blocks as a every-day programming technique"

      Anonyblocks are just another tool in the toolset. I use them primarily in unit test files to separate out tests of a feature or method where I need to instantiate a new object for a test sequence.

      For situations such as yours, I'd probably opt for a function instead of a block that's inline with the code. A subroutine provides the same scoping as the block does:

      sub slurp_file { my ($fname) = @_; local $/; open my $fh, '<', $fname or die "Can't open damned '$fname' file: +$!"; my $data = <$fh>; close $fh or die $!; return $data; }

      To each their own, there's more than one way to do it!

        I use [Anonyblocks] primarily in unit test files to separate out tests of a feature or method where I need to instantiate a new object for a test sequence

        This is also my primary use case. So I can have the same variable names repeated and don’t end up with $mech1 .. $mech10 or $json_116.

        I have the following yasnippets defined in my emacs.

        $ cat ~/.emacs.d/snippets/cperl-mode/slurp # -*- snippet -*- #key: slurp #group: slurp #name: Slurp file-handle # -- my $${1:variable} = do { local $/; <$${2:fh}>; };
        $ cat ~/.emacs.d/snippets/cperl-mode/slurp.open # -*- snippet -*- #key: slurp #group: slurp #name: Open and slurp # -- my $${1:variable} = do {$> local $/;$> open( my $${2:fh}, q{<}, ${3:$WHAT} )$> or die qq{Can't open "$3": $!\n}; <$$2>;$> };$>

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

      "As for unnecessary things like "= undef" and "close $fh" ..."

      That's absolutely fine and your reasoning is sound. As I said: "I'm not saying don't use them: just advising that they're optional".

      "I think that a programming language should stay language that we speak and understand, ..."

      The first time I ever saw a Perl script — a very long time ago; I'm pretty sure it was Perl 3 — I was absolutely amazed that I was able to understand most of it at a glance.

      — Ken