ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
4.3 Using Hard ReferencesJust as there are numerous ways to create references, there are also several ways to use, or dereference, a reference. 4.3.1 Using a Variable as a Variable NameAnywhere you might ordinarily put an alphanumeric identifier as part of a variable or subroutine name, you can just replace the identifier with a simple scalar variable containing a reference of the correct type. For example: $foo = "two humps"; $scalarref = \$foo; $camel_model = $$scalarref; # $camel_model is now "two humps" Here are various dereferences: $bar = $$scalarref; push(@$arrayref, $filename); $$arrayref[0] = "January"; $$hashref{"KEY"} = "VALUE"; &$coderef(1,2,3); print $globref "output\n"; It's important to understand that we are specifically
not dereferencing $refrefref = \\\"howdy"; print $$$$refrefref; You can think of the dollar signs as executing right to left. 4.3.2 Using a BLOCK as a Variable NameThe second way is just like the first, except using a
$bar = ${$scalarref}; push(@{$arrayref}, $filename); ${$arrayref}[0] = "January"; ${$hashref}{"KEY"} = "VALUE"; &{$coderef}(1,2,3); Admittedly, it's silly to use the braces in these simple cases, but
the &{ $dispatch{$index} }(1, 2, 3); 4.3.3 Using the Arrow OperatorFor references to arrays or hashes, a third method of dereferencing
the reference involves the use of the $ $arrayref [0] = "January"; #1 ${ $arrayref }[0] = "January"; #2 $arrayref->[0] = "January"; #3 $ $hashref {KEY} = "F#major"; #1 ${ $hashref }{KEY} = "F#major"; #2 $hashref->{KEY} = "F#major"; #3 You can see from this example that the first print $array[3]->{"English"}->[0]; Note that Suppose now that $array[3]->{"English"}->[0] = "January"; This is one of those cases mentioned earlier in which references
spring into existence when used in an lvalue context. Supposing
One more shortcut here. The arrow is optional between brace- or bracket-enclosed subscripts, so you can shrink the above code down to: $array[3]{"English"}[0] = "January"; Which, in the case of ordinary arrays, gives you multi-dimensional arrays just like C's arrays: $answer[$x][$y][$z] += 42; Well, okay, not entirely like C's arrays. For one thing, C doesn't know how to grow its arrays on demand, while Perl does. Also, there are similar constructs in the two languages that parse differently. In Perl, the following two statements do the same thing: $listref->[2][2] = "hello"; # pretty clear $$listref[2][2] = "hello"; # a bit confusing This second of these statements may disconcert the C programmer, who is
accustomed to using
$listref[$i]->[$j] = "hello"; 4.3.4 Using Object MethodsIf a reference happens to be a reference to an object (a blessed thingy, that is), then there are probably methods to access the innards of the object, and you should probably stick to those methods unless you're writing the class package that defines the object's methods. (Such a package is allowed to treat the object as a mere thingy when it wants to.) In other words, be nice, and don't violate the object's encapsulation without a very good reason. Perl does not enforce encapsulation. We are not totalitarians here. We do expect some basic civility, however. 4.3.5 Other Tricks You Can Do with Hard ReferencesYou can use the ref operator to determine what type of thingy a reference is pointing to. Think of ref as a "typeof" operator that returns true if its argument is a reference and false otherwise. The value returned depends on the type of thing referenced. Built-in types include: REF SCALAR ARRAY HASH CODE GLOB If you simply use a hard reference in a string context, it'll be converted
to a string containing both the type and the address: You can use the bless operator to
associate a referenced thingy with a package functioning as an object
class. When you do this, ref will
return that package name instead of the internal type. An object
reference used in a string context returns a string with both the
external and internal types, along with the address:
Since the dereference syntax always indicates the kind of reference
desired, a typeglob can be used the same way a reference can, despite
the fact that a typeglob contains multiple thingies of various types.
So Here's a trick for interpolating the value of a subroutine call into a string: print "My sub returned @{[ mysub(1,2,3) ]} that time.\n"; It works like this. At compile time, when the print "That yields @{[ $n + 5 ]} widgets\n"; Be careful though. The inside of the square brackets is supplying a
list context to its expression. In this case it doesn't matter,
although it's possible that the above call to print "That yields ${ \($n + 5) } widgets."; 4.3.6 ClosuresEarlier we talked about creating anonymous subroutines with a nameless
You can also think of closures as a way to write a subroutine template without using eval. The lexical variables are like parameters to fill in the template. Here's a small example of how closures work: sub newprint { my $x = shift; return sub { my $y = shift; print "$x, $y!\n"; }; } $h = newprint("Howdy"); $g = newprint("Greetings"); # Time passes... &$h("world"); &$g("earthlings"); This prints: Howdy, world! Greetings, earthlings! Note in particular how This method only applies to my variables. Global variables work as they always worked (since they're neither created nor destroyed the way lexical variables are). By and large, closures are not something you need to trouble yourself about. When you do need them, they just sorta do what you expect.[6]
Perl doesn't provide member pointers like C++ does, but you can get a similar effect using a closure. Suppose you want a pointer to a method for a particular object. You can remember both the object and the method as lexical variables bound to a closure: sub get_method_ref { my ($self, $method) = @_; return sub { return $self->$method(@_) }; } $dog_wag = get_method_ref($dog, 'wag'); &$dog_wag("tail"); # Calls $dog->wag('tail'). |