Perl's "references" let you create pointers to variables, subroutines, constants, anonymous data structures, anonymous subroutines, etc all using the same notation.
A reference is a scalar, it is stored in a scalar variable like a string or number. A collection of them can be stored in an array or a hash as well.
Perl does all the necessary reference counting and garbage collection on everything, so you don't have to worry about dynamic allocation issues.
Create reference to a variable or value by backslashing the value to be referred to. Use dollar-name with the type indicator to de-reference.
$a = 7; $aref = \$a; # scalar aref now reference to scalar a print $aref; # prints SCALAR(0x80bf9a8) or some such nonsense print $$aref; # prints 7 $$aref += 2; # $a now 9 @b = (1, 2, 3); $bref = \@b; # scalar bref now reference to array b print $$bref[0]; # prints 1, $bref for ref name, another $ to access one element $numref = \10; # scalar numref now referencd to value 10 $strref = \"hi there"; # scalar strref now referencd to value "hi there" $subref = \&one; # reference to sub named "one" &$subref; # invoke sub via refCan use them anywhere you'd use the regular variable
push(@$bref, 4, 5); print "$b[3], $$bref[4]\n", # prints 4, 5Alternative, easier notation for deref'ing with arrays and hashes on a single value:
print "$bref->[0]\n"; print "$href->{"name"}\n";The function ref will test a scalar and see if it is a reference or not. Will return false if the scalar contains a number or string, otherwise a string telling you what kind of reference it contains:
Note how the arrays passed to sub get "flattened" into single array.
#!/usr/bin/perl -w sub printer { foreach $element (@_) { print "$element\n"; } } @one = (1, 2, 3); @two = (8, 9, 10); printer @one, @two;
Solve this by using references in passing our data.
#!/usr/bin/perl -w sub printer { foreach $element (@_) { print "array start\n"; foreach $item (@$element) { print "$item\n"; } } } @one = (1, 2, 3); @two = (8, 9, 10); printer \@one, \@two;
$refvalue = \10;Arrays (note square brackets):
$refarray = [1, 3, 5]; # anonymous array created with 3 values foreach $value (@$refarray) { print $value; }Hashes (note curly braces):
$refhash = {"key1", "value1", "key2", "value2"}; # anon hash with 2 k/v pairs foreach $key (sort reverse keys %$refhash) { print "$$refhash{$key}\n"; # $$ for one value through a reference }
Perl does reference counting and garbage collection.
Things that go out of scope don't necessarily go away right away, wait until reference count goes to zero.
{ my $x = 7; # declare and use $x in a block with my $x++; $xref = \$x; # create reference to it } print "x is now: $x\n"; # errors: "main::x only used once" # "Use of uninitialized value" print "x is now: $$xref\n"; # ok: can use ref.
$a = 10; $aref = \$a; $arefref = \$aref; $arefrefref = \$arefref; print "please shoot me with $$$$arefrefref bullets if I ever write this code\n";
#!/usr/bin/perl -w # create array of references to anonymous arrays @array2d = ( [1, 2, 3], [4, 5, 6], [7, 8, 9]); print "center value is: $array2d[1]->[1]\n"; print "center value is: $array2d[1][1]\n";
Can create things piece-by-piece, autovivification.
$arrayfoo[1][2] = 7; # arryfoo springs into existance with an # undef value and a ref to another anon array # with 3 elmts: 2 undefs and a 7
Exercise: imagine putting more than just numbers in each position, say another array or a hash as more references...
Can create complex structures using references.
#!/usr/bin/perl -w %greg = ('name' => "Greg", # not reference 'age' => 31); %bridget = ('name' => "Bridget Fonda", # not reference 'age' => 36); %winona = ('name' => "Winona Ryder", # not reference 'age' => 29) ; @wives = (\%bridget, \%winona); # create list of desired wives, references $greg{'wives'} = \@wives; # assign to rightful person, reference print "wife one is: $greg{'wives'}->[0]->{'name'}\n"; print "wife two is: $greg{'wives'}[1]{'name'}\n";
Or we can do it with only a single named variable and lots of anonymous data.
#!/usr/bin/perl -w %greg = ('name' => "Greg", 'age' => 31, 'wives' => [ { 'name' => "Bridget Fonda", 'age' => 36 }, { 'name' => "Winona Ryder", 'age' => 29 }, ] ); print "wife one is: $greg{'wives'}->[0]->{'name'}\n"; print "wife two is: $greg{'wives'}[1]{'name'}\n";
Use standard Data::Dumper module to help understand what is in your code. You can read it's output and "eval" it back into your code.
#!/usr/local/bin/perl -w use Data::Dumper; $foo = [ { name => 'Greg', age => 32, }, { name => 'Winona', age => 29, }, ]; print "$foo->[0]{age}\n"; print Data::Dumper->Dump([$foo], ["foo"]); # list of data, list of names output: 32 $foo = [ { 'age' => 32, 'name' => 'Greg' }, { 'age' => 29, 'name' => 'Winona' } ];