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


Requiring Variables Rather than Values - Page 17

July 13, 2001

So far we have seen how to enforce a specific number of arguments and their scope, if not their data type. We can also use prototypes to require that an actual variable be passed. This is invaluable when we want to implement a subroutine that modifies its passed parameters, such as the capitalize example just above.

To require a variable, we again use a $, @, and % character to specify the type, but now we prefix it with a backslash. This does not, as it might suggest, mean that the subroutine requires a reference to a scalar, array, or hash variable. Instead, it causes Perl to require a variable instead of merely a value. It also causes Perl to automatically pass the variable as a reference:

#!/usr/bin/perl
# varproto.pl
use warnings;
use strict;

sub capitalize (\$) {
  ${$_[0]} = ucfirst (lc ${$_[0]});
}

my $country = "england";
capitalize $country;
print $country, "\n";
# capitalize "scotland"; # ERROR: compile-time syntax error!

If we tried to call capitalize with a literal string value, we would get the error:

Type of arg 1 to main::capitalize must be scalar (not constant item) at ..., near ""england";"

The fact that Perl automatically passes variables as references is very important, because it provides a new way to avoid the problem of list flattening. In other words, prototypes allow us to pass arrays and hashes to a subroutine as-is, without resorting to references in the subroutine call.

A push is an example of a built-in function that works by taking an array as its first argument. We do not need to treat that variable specially to avoid flattening, and we can replicate that syntax in our own code by defining a prototype of (\@@). The following subroutine uses the list- processing version of capitalize to produce a capitalizing push subroutine. First it removes the array variable using shift, then capitalizes the rest of the arguments and adds them to the variable with push. Perl, being versatile, lets us do the whole thing in one line:

sub pushcapitalize (\@@) {
  push @{shift}, capitalize(@_);
}

We can use this subroutine just like we use the push function

pushcapitalize @countries, "england";
pushcapitalize @countries, "scotland", "wales";
pushcapitalize @countries, @places; # no flattening here!

Note that we omitted the parentheses, which requires that the subroutine be either already defined or predeclared.

Hash variables are requested using \%, which unlike % does have a different meaning to its array counterpart \@. Here is an example that flips a hash variable around so that the keys become values and the values become keys. If two keys have the same value one of them will be lost in the transition, but for the sake of simplicity we'll ignore that here:

sub flip (\%) {
  @hash = %{$_[0]};
  %{$_[0]} = reverse @hash;
}

This subroutine makes use of the fact that a hash is essentially just a list with an even number of values, and a little extra cleverness allows quick key access. So, to flip the hash we turn it into a list and reverse it. This also reverses each key-value pair with respect to each other; we then turn it back into a hash again.

Although Perl will automatically pass variables as references when a variable prototype is in effect, it will allow an explicit reference if we dereference it first. The two following calls are both valid uses of the above subroutines:

For the pushcapitalize subroutine:

pushcapitalize @{$countries_ref}, "england";

And for the flip subroutine:

flip %{$hash_ref};

Before we finish with variable prototypes it is worth mentioning, just for completeness, that \& also has a meaning subtly different from &. It requires that the passed code reference be a reference to an actual subroutine, that is, a code reference defined using $coderef = sub {...} or $coderef = \&mysubroutine. A reference to an in line bare block (such as in mysub {...} @list) will not be accepted. Another way to look at \ is that it requires that the argument actually starts with the character it precedes: \& therefore means that the argument must start &, not {.

Prototyping Code References - Page 16
Professional Perl Programming
Optional Parameters - Page 18


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




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