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

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

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

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

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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



11.4. Taking References to Functions


11.4.1. Problem


You need to manipulate a subroutine by
reference. This might happen if you need to create a signal handler,
a Tk callback, or a hash of function pointers.

11.4.2. Solution


To get a code reference:

$cref = \&func;
$cref = sub { ... };

To call a code reference:

@returned = $cref->(@arguments);
@returned = &$cref(@arguments);

11.4.3. Discussion


If the name of a function is func, you can produce
a reference to it by prefixing its name with
\&. You can also dynamically allocate
anonymous functions using the sub {
} notation. These code references can be stored just like
any other reference.

It is possible to store the name of a function in a variable, such as:

$funcname = "thefunc";
&$funcname( );

but that's not a very good solution for several reasons. First, it
uses symbolic references, not real (hard) references, and so is
forbidden under the use strict
"refs" pragma. Symbolic references to variables
are usually a bad idea, since they can't access lexical variables,
only globals, and aren't reference counted. Second, as written it
doesn't include package information, so if executed in a different
package, it would try to call the wrong function. Finally, in the odd
case that the function were redefined at some point, the symbolic
reference would get whatever the current definition for the function
was, whereas the hard reference would still access the old
definition.

Instead of placing the name of the function in the variable, use the
backslash operator to create a reference to the function. This is the
normal way to store a function in a variable or pass along to another
function. You can mix and match references to named functions with
references to unnamed ones:

my %commands = (
"happy" => \&joy,
"sad" => \&sullen,
"done" => sub { die "See ya!" },
"mad" => \&angry,
);
print "How are you? ";
chomp($string = <STDIN>);
if ($commands{$string}) {
$commands{$string}->( );
} else {
print "No such command: $string\n";
}

If you create an anonymous function that refers to a lexical
(my) variable from an enclosing scope, reference
counting ensures that the lexical variable is never deallocated so
long as that function reference exists:

sub counter_maker {
my $start = 0;
return sub { # this is a closure
return $start++; # lexical from enclosing scope
};
}
$counter = counter_maker( );
for ($i = 0; $i < 5; $i ++) {
print &$counter, "\n";
}

Even though counter_maker has ended and
$start gone out of scope, Perl doesn't free the
variable, because the anonymous subroutine referenced by
$counter still has a reference to
$start. If we call
counter_maker again, it'll return another,
different anonymous subroutine reference that uses a
different $start:

$counter1 = counter_maker( );
$counter2 = counter_maker( );
for ($i = 0; $i < 5; $i ++) {
print &$counter1, "\n";
}
print &$counter1, " ", &$counter2, "\n";
1
2
3
4
5 0

Closures are often
used in callback routines. In graphical and other event-based
programming, you associate code with a keypress, mouse click, window
expose event, etc. The code will be called much later, probably from
an entirely different scope. Variables mentioned in the closure must
be available when it's finally called. To work properly, such
variables must be lexicals, not globals.

Another use for closures is function generators, that is, functions
that create and return brand-new functions. The
counter_maker function is such a function
generator. Here's another simple one:

sub timestamp {
my $start_time = time( );
return sub { return time( ) - $start_time };
}
$early = timestamp( );
sleep 20;
$later = timestamp( );
sleep 10;
printf "It's been %d seconds since early.\n", $early->( );
printf "It's been %d seconds since later.\n", $later->( );
It's been 30 seconds since early.
It's been 10 seconds since later.

Each call to timestamp generates and returns a
brand-new function. The timestamp function creates
a lexical called $start_time that contains the
current clock time (in epoch seconds). Every time that closure is
called, it returns how many seconds have elapsed since it was created
by subtracting its starting time from the current time.

11.4.4. See Also


The section on "Closures" in Chapter 8 of Programming
Perl
and the discussion on closures in
perlref(1);
Recipe 10.11;
Recipe 11.4



11.3. Taking References to Hashes11.5. Taking References to Scalars




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

/ 875