http://qs321.pair.com?node_id=468992

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

Hi Monks,

I've just been bitten by this feature of perl:
#!/usr/bin/perl use strict; use warnings; { local $/ = 'Foo'; my $obj = SomePackage->new; }; package SomePackage; sub new { my ($class) = shift; print "Whats the separator?: $/ :\n"; return bless {} , $class; };

I expected that $/ would be package specific, it doesnt seem to be,
My question is , how best to avoid this mistake or is there a way to alter the behaviour of $/ to make it package specific?

Many Thanks, Ian (monkey_boy)


This is not a Signature...

Replies are listed 'Best First'.
Re: non-global $/
by halley (Prior) on Jun 22, 2005 at 13:37 UTC
    Well, that's exactly what local does. Think of each variable name as referring to a stack of variables instead of just one. The local keyword pushes on a new value for a while, and at the end of its scope, the top value is popped and discarded. Other subroutines which might use that same variable will still see the top value.

    All of the built-in "punctuation" variables are globals, not package variables. The exception are the two "default" variables, $_ and @_, which (1) get localized values automatically in many situations, and (2) assume the 'main::' package if not otherwise specified.

    To avoid the problem, don't do a local and call subroutines that are outside your control. The need to redefine $/ or other built-in vars should be really confined to one or two low-level statements which use those variables to tune their behavior.

    --
    [ e d @ h a l l e y . c c ]

Re: non-global $/
by hanenkamp (Pilgrim) on Jun 22, 2005 at 13:44 UTC

    I'm not certain why you need this, but here's the deal. The $/ is a global variable. Adding the local before setting $/ to "Foo" makes it local to that block and anything you call from that block. The only way I know of to make a global "package specific" is to locally reset it to your desired package version at the start of every method (again using the local keyword.

    Personally, I tend to just avoid the globals whenever I can.

Re: non-global $/
by tlm (Prior) on Jun 22, 2005 at 14:11 UTC

    I expected that $/ would be package specific, it doesnt seem to be,
    ...is there a way to alter the behaviour of $/ to make it package specific?

    From perlvar:

    Perl identifiers that begin with digits, control characters, or punctuation characters are exempt from the effects of the "package" declaration and are always forced to be in package "main"; they are also exempt from "strict ’vars’" errors. A few other names are also exempt in these ways:

                   ENV             STDIN
                   INC             STDOUT
                   ARGV            STDERR
                   ARGVOUT         _
                   SIG
    
    In particular, the new special "${^_XYZ}" variables are always taken to be in package "main", regardless of any "package" declarations presently in scope.

    the lowliest monk

Re: non-global $/
by trammell (Priest) on Jun 22, 2005 at 14:11 UTC
    While doing some research on On bad habits related to $^L, I stumbled across this bit in the POD for IO::Handle:
    See perlvar for complete descriptions of each of the following support +ed "IO::Handle" methods. All of them return the previous value of th +e attribute and takes an optional single argument that when given wil +l set the value. If no argument is given the previous value is uncha +nged (except for $io->autoflush will actually turn ON autoflush by de +fault). $io->autoflush ( [BOOL] ) $| $io->format_page_number( [NUM] ) $% $io->format_lines_per_page( [NUM] ) $= $io->format_lines_left( [NUM] ) $- $io->format_name( [STR] ) $~ $io->format_top_name( [STR] ) $^ $io->input_line_number( [NUM]) $. The following methods are not supported on a per-filehandle basis. IO::Handle->format_line_break_characters( [STR] ) $: IO::Handle->format_formfeed( [STR]) $^L IO::Handle->output_field_separator( [STR] ) $, IO::Handle->output_record_separator( [STR] ) $\ IO::Handle->input_record_separator( [STR] ) $/
    I had been hoping to see that there was a per-filehandle setting for $^L; apparently $/ falls in the same category. My question is: is this due to some fundamental restriction of filehandles? If not, it would be nice to have more extensive per-filehandle attributes. I suppose this is "fixed" in Perl6...
Re: non-global $/
by broquaint (Abbot) on Jun 22, 2005 at 15:01 UTC
    As others have mentioned you want to use local to limit changes to the likes of $/ within the given dynamic scope. For further information on what variables are really global, see. Can you create *real* global variables?.
    HTH

    _________
    broquaint

Re: non-global $/
by Ultra (Hermit) on Jun 22, 2005 at 13:49 UTC

      Nope. my() doesn't care about packages.

      use strict; my $x = 5; print "\$x in main package=$x\n"; package other; print "\$x in other package=$x\n";

      Jenda
      XML sucks. Badly. SOAP on the other hand is the most powerfull vacuum pump ever invented.

        Indeed, but in his context, my would be more suited.

        Update: Thanks monkey_boy for pointing me that Can't use global $/ in "my"
        Dodge This!