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


Passing Parameters - Page 9

July 13, 2001

Basic Perl subroutines do not have any formal way of defining their arguments. We say 'basic' because we can optionally define a prototype that allows us to define the types of the arguments passed, if not their names inside the subroutine. However, ignoring prototypes for the moment, we may pass any number of parameters to a subroutine:

mysubroutine ("parameter1", "parameter2", 3, 4, @listparameter);

It is helpful to think of the parentheses as a conventional list definition being passed to mysubroutine as a single list parameter – remove mysubroutine from the above statement and what we are left with is a list. This is not far from the truth, if we recall that declaring a subroutine prior to using it allows us to use it as if it were a built-in list operator. Consequently, arrays and hashes passed as arguments to subroutines are flattened into one list internally, just as they are when combined into a larger list.

The parameters that are passed into a subroutine appear inside the subroutine as a list contained in the special variable @_. This variable is made local to each subroutine, just as $_ is inside nested foreach loops. The definition of @_ is thus unique to each subroutine, despite the fact that @_ is a package variable.

One simple and common way to extract parameters passed to a subroutine is simply to assign @_ to a list of scalar variables, like so:

sub volume {
  ($height, $width, $length) = @_;
  return $height * $width * $length;
}

This gives us named scalar variables we can write code for more legibly, and also takes care of any aliasing problems that might otherwise occur (as we will see in a moment). Alternatively, we can use shift to pull values off the array one by one:

sub volume {
  $height = shift;
  $width = shift;
  $length = shift;
  return $height * $width * $length;
}

This differs from the previous example in that it actually modifies @_, removing passed parameters from the front of the list. After all the shifts have been processed @_ may be empty or it may contain further passed parameters. We can use that to our advantage to write subroutines that only use some parameters and pass the rest on. For example, here is a speculative object method that is a wrapper for the volume function:

sub volume {
  my $self = shift;
  #remove the object passed as the first parameter
  return Functions::volume(@_);
  #pass remaining parameters on
}

If it's brevity we are after, we can avoid assigning the contents of @_ to anything, and simply use the values of @_ directly. This version of volume is not as clear as the first, but makes up for it by being only one line long. As a result the workings of the subroutine are still fairly obvious:

sub volume {
  return $_[0] * $_[1] * $_[2];
}

The @_ array is a local array defined when the subroutine is first entered. However, while the array is local, the values of @_ are aliases for the original parameters that were passed in to the subroutine. This means that, if the parameter was a variable, modifying the values in the @_ array modifies the original variable as well. Used unwisely this can be an excellent way to create hard-to- understand and difficult-to-maintain code, but if the purpose of a subroutine is to manipulate a list of values in a consistent and generic way, it can be surprisingly useful. Here is an example of such a subroutine that emulates the chomp function:

#strip the line separator '$/'
#from the end of each passed string:
sub mychomp {
  foreach (@_) {
    s|$/$||
    ;
  }
}

[Lines 4 and 5 above are one line. They have been split for formatting purposes.]

This also happens to be a good demonstration of aliasing. The subroutine actually aliases twice over; once to alias the variables $string and @lines in the @_ array inside the subroutine, and again in the foreach loop that aliases the loop variable $_ to the values in the @_ array one by one.

We can call this subroutine in the same way as the real chomp:

mychomp $string;
mychomp @lines;

Modifying the passed arguments implies that they are modifiable in the first place. Passing a literal value rather than a variable will produce a syntax error. For example:

mychomp "you can't touch this \n";

This produces:

Modification of a read-only value attempted at ...

When we come to discuss prototypes we will see how we can define subroutines that can be checked for correct usage at compile time. This means we can create a subroutine like mychomp that will produce a syntax error if used on a literal variable at compile time, just like the real chomp.

Checking for Subroutines and Defining Subroutines On the Fly - Page 8
Professional Perl Programming
Passing Lists and Hashes - Page 10


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