Web Developer's Virtual Library: Encyclopedia of Web Design Tutorials, Articles and Discussions


WDVL Newsletter

Active Server Pages
JSP/Java Servlets
Microsoft SQL Server
Daily Backup
Dedicated Servers
Streaming Audio/Video
24-hour Support    

jobs.webdeveloper.com

Hiermenus


e-commerce
Partner With Us















Developer Channel
FlashKit.com
JavaScript.com
JavaScriptSource
Developer Jobs
ScriptSearch
StreamingMediaWorld
Web Developer's Journal
Web Developer's Virtual Library
WebDeveloper.com
Webreference
Web Hosts
XMLfiles.com

internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers


Take my Parameters, Please

March 13, 2000

Another great use for references is passing data between subroutines. In theory, most well-designed Perl programs will contain subroutines to perform repetitive or specialized tasks. Let's say that you have a subroutine &summary, which takes two parameters: a label (scalar) and a list of surnames. The subroutine creates some sort of chart of these names using the label as a header -- the trick here is that you need to pass one scalar and one list to the subroutine. Your instinct might be to construct a call such as:

print &summary($label,@surnames);

But this would be wrong, so very wrong. Why? Because a subroutine accepts parameters as a flat list into the built-in list variable @_; that means the above call would simply pass the value of $label followed by each of the items in @surnames as one long list. Whereas, your subroutine will want to receive only two values; the first being a scalar, the second being one list.

Instead, you want to pass a reference to the list; because the reference is a scalar, it travels lightly into the subroutine, which can then dereference it into a list. Sound confusing? Here's the call:

print &summary($label,\@surnames);

And here is the beginning of the subroutine:

sub summary {
my ($label,$surnameRef)=@_;
my @surnames=@{$surnameRef};
print "Title: $label\n"; 
print join (",",@surnames);
etc... 
}

An important point to remember here occurs in line two above; two local variables receive the parameters from the incoming list @_. The second parameter is a scalar because it is receiving a reference; therefore, $surnameRef itself becomes a reference to the array referenced by \@surnames in the calling statement. To use this list in list context, we need to dereference, which here is done by dereferencing $surnameRef into a normal list variable @surnames. We could have dereferenced on-the-fly in the join() function, as follows, which is more efficient but slightly more obtuse to read:

print join (",",@{$surnameRef});

When passing data between subroutines, you can think of references as an effective way to package or cloak a complex data structure and pass it wholly into a subroutine, where it can be unpackaged -- or dereferenced -- into its data structure, be it a list or a hash. Of course, keep in mind that the reference only points to data, which means if the data pointed to changes, the data you get by dereferencing changes.

Taking this example one step further, imagine that you want to pass a particular hash into a subroutine, and that subroutine will return a different hash.

%grades=("Tom Jones"=>92,"Briget 
Gidget"=>85);
$label="Grade Summary";
print &summary($label,\%grades)->{"header"};
print "<TABLE>".&summary($label,\%grades)->{"body"}."</TABLE>";

sub summary {
my ($label,$grades)=@_;
my %tables=("header"=>"","body"=>"");
$tables{"header"}="<H2>$label</H2>";
foreach $key (keys %{$grades}) {
$tables{"body"}.="<TR><TD>$key</TD><TD>$grades->{$key}</TD></TR>";
}
return \%tables;
}

Admittedly, this final example may take a second read or two. Or three. The goal of this program will be to output HTML code of a table that summarizes the grades contained in the %grades hash. First, we create a typical hash, and a scalar containing a label. Now we get tricky. The first print statement calls the &summary subroutine, passing it $label and a reference to the %grades hash. Ultimately, the subroutine returns a reference to a hash of results, one key of which is "header". So, think of the whole subroutine call as one big hash reference. As such, we dereference the subroutine call to retrieve the value of the "header" key.

The same concept applies to the second print statement. Again, the entire &summary subroutine is treated as a hash reference, because that is what it returns. And so we dereference the "body" key.

Turning to the subroutine itself, it accepts the two parameters into a local scalar and a local reference, $grades. The local hash %tables is built to contain the results, and the value for the "header" key is assigned. A tricky foreach loop dereferences $grades to pull out its keys, and iterates over each key. For each key, an HTML table row is constructed using the key and the key's value, dereferenced again from $grades. And that's just two lines of code!

The HTML that is built is then concatenated into the value of the "body" key for our local %tables hash. Finally, the subroutine returns a reference to this hash -- that is what lets us treat this subroutine as if it is one big hash reference, as seen in the print statement.

Shall we dance, sweet reference?
The Perl You Need to Know
Come Sail Away


Up to => Home / Authoring / Languages / Perl / PerlfortheWeb




Jupiter Online Media: internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and Jupiter Online Media

Jupitermedia Corporate Info


Legal Notices, Licensing, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers