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

Redefining $/ in main program affects subrotines in other modules. How to solve it in main? How to solve it in module? What's the best practice? In this example subroutine will not return the firts line of file:
# in main use strict; use reader; $/= "\n\n\n"; while(<>){ my ($filename)=/^(\S+)/; my $text=reader::firstline($filename); } ### # in file "reader.pm" package reader; sub firstline{ open(my $fh,"<", $_[0]); return <$fh>; } 1;

Replies are listed 'Best First'.
Re: Scope of $/
by NetWallah (Canon) on May 26, 2016 at 01:12 UTC
    Limit the scope of the changed value of $/, by "local"izing it, and enclosing it in the smallest block possible:
    { # Add an enclosing block local $/= "\n\n\n"; while(<>){ local $/="\n"; # Reset to normal behaviour inside loop only my ($filename)=/^(\S+)/; my $text=reader::firstline($filename); } } # End enclosing block.
    This code avoids "Action at a distance", by making wierd settings in as limited a scope as possible.

            This is not an optical illusion, it just looks like one.

      A truly minimal scope solves the problem.
      use strict; use reader; #$/= "\n\n\n"; while(do{local $/="\n\n\n"; $_=<>}){ my ($filename)=/^(\S+)/; my $text=reader::firstline($filename); }

      Update: Commented out original definition of $/.

      Bill
        Applause, for a truly elegant solution !

        I wish I had thought of that.

                This is not an optical illusion, it just looks like one.

      The enclosing block is just noise :) unless you give it a name

        That is not true. No name is required. The {} set the scope of the local. For my demo below, I used an "our" variable, package scope. A Perl Global like $/ acts similar. You cannot localize a "my" variable.

        I guess you can think of a local var as sort of like creating a stack of that variable. The local statement is like a "push" and when you exit the scope of the local, that is like a "pop". Rough analogy, but that is descriptive of the behavior.

        #!usr/bin/perl use warnings; use strict; our $x = 1; #a package variable { print "$x\n"; #prints 1 local $x = 99; print "$x\n"; #prints 99 } print "$x\n"; #prints 1, back to before the "local"
Re: Scope of $/
by Anonymous Monk on May 26, 2016 at 00:46 UTC
    Its a global variable, so use local and set the variable to what you need it to be, as in
    sub firstline { use autodie qw/ open /; local $/ = "\n"; open my($fh),'<',$_[0]; return scalar <$fh>; }
Re: Scope of $/
by agarrubio (Novice) on May 26, 2016 at 23:39 UTC

    Thanks all!

    BillKSmith's method works nicely, However, with NetWallah's, method the altered value of $/ is still visible to the subroutine called inside the main reading loop (reader::firstline).

    Reinstateing with local the value of $/ inside the subroutine also works, but I guess it is not a standard precuation in most modules