Perl Cd Bookshelf [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Perl Cd Bookshelf [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



10.13. Saving Global Values


10.13.1. Problem


You need to temporarily save
away the value of a global variable.

10.13.2. Solution


Use the
local operator to save a previous global value,
automatically restoring it when the current block exits:

our $age = 18; # declare and set global variable
if (CONDITION) {
local $age = 23;
func( ); # sees temporary value of 23
} # Perl restores the old value at block exit

10.13.3. Discussion


Despite its name, Perl's local operator does not
create a local variable. That's what my does.
Instead, local merely preserves an existing value
for the duration of its enclosing block. Hindsight shows that if
local had been called
save_value instead, much confusion could have
been avoided.

Three places where you must use
local instead of my are:


  • You need to give a global variable a temporary value, especially
    $_.


  • You need to create a local file or directory handle or a local
    function.


  • You want to temporarily change just one element of an array or hash.


  • 10.13.3.1. Using local( ) for temporary values for globals


    The first situation is more apt to
    happen with predefined, built-in variables than with user variables.
    Often these are variables that Perl consults for hints for its
    high-level operations. In particular, any function that uses
    $_, implicitly or explicitly, should certainly
    have a local $_. This is annoyingly easy to forget
    to do. See
    Recipe 13.15 for one solution to
    this.

    Another common target for local is the
    $/ variable, a global that implicitly affects the
    behavior of the readline operator used in
    <FH> operations.

    $para = get_paragraph(*FH); # pass filehandle glob
    $para = get_paragraph(*FH); # pass filehandle by glob reference
    $para = get_paragraph(*IO{FH}); # pass filehandle by IO reference
    sub get_paragraph {
    my $fh = shift;
    local $/ = '';
    my $paragraph = <$fh>;
    chomp($paragraph);
    return $paragraph;
    }

    10.13.3.2. Using local( ) for local handles


    The
    second situation used to arise whenever you needed a local filehandle
    or directory handle—or more rarely, a local function.

    $contents = get_motd( );
    sub get_motd {
    local *MOTD;
    open(MOTD, "/etc/motd") or die "can't open motd: $!";
    local $/ = undef; # slurp full file;
    local $_ = <MOTD>;
    close (MOTD);
    return $_;
    }

    If
    you wanted to return the open filehandle, you'd use:

    return *MOTD;

    However, in modern releases of Perl, you would make use of the
    filehandle autovivification property:

    $contents = get_motd( );
    sub get_motd {
    my $motd; # this will be filled in by the next line
    open($motd, "/etc/motd") or die "can't open motd: $!";
    local $/ = undef; # slurp full file;
    return scalar <$motd>;
    }

    When the function returns, the anonymous filehandle is automatically
    closed for you. However, if you'd chosen to return
    $motd, then it wouldn't be. This is explained more
    fully in the
    Introduction to Chapter 7.

    10.13.3.3. Using local( ) on parts of aggregates


    The third situation is exceedingly rare, except for one common case.
    Because the local operator is really a "save value" operator, you can
    use it to save off just one element of an array or hash, even if that
    array or hash is itself a lexical!

    my @nums = (0 .. 5);
    sub first {
    local $nums[3] = 3.14159;
    second( );
    }
    sub second {
    print "@nums\n";
    }
    second( );
    0 1 2 3 4 5
    first( );
    0 1 2 3.14159 4 5

    The only common use for this kind of thing is for temporary signal
    handlers.

    sub first {
    local $SIG{INT} = 'IGNORE';
    second( );
    }

    Now while second is running, interrupt signals are
    ignored. When first returns, the previous value of
    $SIG{INT} is automatically restored.

    Although a lot of old code uses local, it's
    definitely something to steer clear of when it can be avoided.
    Because local still manipulates the values of
    global variables, not local variables, you'll run afoul of
    use strict unless you declared
    the globals using our or the older
    use vars.


    The
    local operator produces dynamic
    scoping
    or runtime scoping. This
    is in contrast with the other kind of scoping Perl supports, which is
    much more easily understood. That's the kind of scoping that
    my provides, known as lexical
    scoping
    , or sometimes as static or
    compile-time scoping.

    With dynamic scoping, a variable is accessible if it's found in the
    current scope—or in the scope of any frames (blocks) in its
    entire subroutine call stack, as determined at runtime. Any functions
    called have full access to dynamic variables, because they're still
    globals, just ones with temporary values. Only lexical variables are
    safe from such tampering.

    Old code that says:

    sub func {
    local($x, $y) = @_;
    #....
    }

    can almost always be replaced without ill effect by the following:

    sub func {
    my($x, $y) = @_;
    #....
    }

    The only case where code can't be so upgraded is when it relies on
    dynamic scoping. That would happen if one function called another,
    and the latter relied upon access to the former's temporary versions
    of the global variables $x and
    $y. Code that handles global variables and expects
    strange action at a distance instead of using proper parameters is
    fragile at best. Good programmers avoid this kind of thing like the
    plague. (The solution is to explicitly pass values as parameters,
    rather than storing them in shared global variables.)

    If you come across old code that uses:

    &func(*Global_Array);
    sub func {
    local(*aliased_array) = shift;
    for (@aliased_array) { .... }
    }

    this should probably be changed into something like this:

    func(\@Global_Array);
    sub func {
    my $array_ref = shift;
    for (@$array_ref) { .... }
    }

    They're using the old pass-the-typeglob strategy devised before Perl
    supported proper references. It's not a pretty thing.

    10.13.4. See Also


    The local, my, and
    our functions in Chapter 29 of
    Programming Perl and
    perlfunc(1); Chapter 6 of Programming
    Perl
    ; the section on "Scoped Declarations" in Chapter 4
    of Programming Perl; the sections on "Private
    Variables via my( )" and "Temporary Values via local( )" in
    perlsub(1);
    Recipe 10.2;
    Recipe 10.16



    10.12. Handling Exceptions10.14. Redefining a Function




    Copyright © 2003 O'Reilly & Associates. All rights reserved.

    / 875