T
thumb_42
Thomas Deschepper said:I've been reading Beginning Per & Programming Perl from O'Reilly for some time
now and I'm getting used to references and how to grow them..
But why would someone use a reference if they can use a normal variable? Yeah, I
know, with references you can grow complex data structures, but in simple
programs, why would you use them (=references)?
Thanks for your (smart) answers
Aside from making it more efficient, references are handy ways of tracking
variables when processing stream data. Parsing an XML document and storing
the character data is an example:
Say you want something like:
$NAMES{E2620} = "John";
And an XML document with ah, <Employee id="E2620">John</Employee>
$garbage = "";
$char_ptr = \$garbage;
Using a reference you could do this:
# Start an element.
$start = sub {
my($expat,$tag) = (shift,shift);
my(%ats) = @_;
# For a complex structure, the tagname should be table driven,
# another use of references, since the table of expected tags
# will change with each parent tag.
if($tag eq 'Employee'){
my($id) = $ats{id}; # Get employee ID from id="E2620".
$NAMES{$id} = ""; # Clear, and make it a string.
$char_ptr = \$NAMES{$id}; # We want our CDATA here now.
}
};
# Deal with CDATA.
$char = sub {
shift; # Get rid of expat.
$$char_ptr .= shift; # Store character data to whatever area.
};
$end = sub {
...
clear $garbage,
put $char_ptr back to $garbage, or parent,
or wherever you need to store the CDATA from here.
..
};
Using a reference, you don't need to have much logic in your character
handler. (In the above case, it'd be simple to just:
if($id) {
$NAME{$id} .= shift;
}
Try doing that if you need chardata from several XML elements to several
hash elements. (probably most of us have tried the 'non-reference' approach
when learning XML:arser, increasing the sale of aspirin.. ) If you
don't use references you'll end up tracking which ID, obtain the
current_element() determine which hash element (of which hash variable) to
store your chardata and it gets really messy.
That same bit of 'state logic' helps when parsing other kinds of data, too.
(any time you need to store stuff some place dependent on some prior bit
of info you got from the stream)
So references take what could be a complicated script and turn it into a
simple one. I've simplified a LOT of stuff this way.
There are times when I don't like references, it's a style issue.
an example is a cursor type of implementation:
package MyCursor;
# init.. or whatever you need to do to create $self with a filehandle, etc..
sub fetch {
my($self) = shift;
# Do what is needed for the next "row","entry","thingy".
return(%row);
}
1;
You could return \%row, and it'd probably be faster but then you'd have a
variable that was lexically scoped to MyCursor::fetch() and that just "feels
wrong" to me. (if %row were a large hash, then it's different) Feels better
to have my(%row) = $cursor->fetch(); then my($row) = $cursor->fetch(); I
regard that as a personal choice. (can always use 'wantarray()' and
do either if you're a people pleaser. <g> )
Jamie