Item 33: Build C-style structs with anonymous hashes.


People often ask me whether Perl has "real data structures, like C." I am forced to answer the same way that I answer questions about lists of lists:

"Well, yes . . . and no."

You already know that there are only a few data types in Perl: scalars, arrays, hashes, subroutines, plus a few odds and ends like filehandles. Structures, like those used in C or Pascal, are not among those types. So in one sense, Perl doesn't have structures. But, on the other hand, hashes provide a very similar effect:

 $student{'last'} = 'Smith';  $student{'first'} = 'John';  $student{'bday'} = '01/08/72'; 

When referring to an element of a hash, you can omit the quote marks around the key so long as it is a valid Perl identifier:

 $student{last} = 'Smith'; 

This looks somewhat like an element of a structure, doesn't it? Your first reaction to this might be something like, "Eww, that's using a string to look up a member of a structure! That's horribly inefficient! A real structure would use some kind of numeric offset computed by the compiler." However, this is wishful thinking where Perl is concerned , and you shouldn't let it bother you at all. [3] Perl is an interpreted language. Accessing variables and elements of arrays and hashes is relatively slow no matter what. The time required to look up an element of a hash is of little consequence in the grand scheme of things.

[3] Perl may eventually optimize certain cases like $foo->{bar} into array accesses , but in most cases this would not provide a dramatic increase in speed.

"Structures" made out of hashes can be passed into subroutines and put to use there:

 sub student_name {    my %student = @_;    "$student{first} $student{last}";  }  print student_name(%student); 

Now, this may look useful, but it is not particularly efficient. When you pass a hash as an argument, what you are actually doing is unrolling the hash into a list of elements, then reading those elements back into an entirely new hash inside the subroutine. There are also some syntactic limitations. You can't easily pass two hashes this way:

 sub roommates {    my %roomie1 = @_;    my %roomie2 = ???? 

OOPS roomie1 ate all the args.

So, although hashes are the right general idea, they aren't perfect. What works better is using references to hashes and, in particular, using anonymous hash constructors to create them:

 $student = {    last => 'Smith',    first => 'John',    bday => '01/08/72'  }; 

You also can create an empty structure and fill it in one piece at a time. Using the arrow syntax to access the members of your "structures" makes things look even more like C or C++:

 $student = {};  $student->{last} = 'Smith';  $student->{first} = 'John';  $student->{bday} = '01/08/72'; 

Quotes aren't required around identifiers inside braces.

Because you are manipulating scalars, not hashes, passing them into subroutines is more efficient, and passing more than one at a time is no problem:

 sub roommates {    my ($roomie1, $roomie2) = @_;    # clever code left as exercise ...  }  roommates($student1, $student2); 

This technique is the basis for the way that objects are constructed in most Perl classes. For more about object-oriented Perl, see Item 49. For more ways to use anonymous hashes, see Item 27.



Effective Perl Programming. Writing Better Programs with Perl
Effective Perl Programming: Writing Better Programs with Perl
ISBN: 0201419750
EAN: 2147483647
Year: 1996
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net