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


Determining and Responding to the Calling Context - Page 21

July 27, 2001

Sometimes it is useful to know what the calling context is, so we can return different values based on the caller's requirements. The return statement already knows this implicitly, and makes use of the context to save time, returning a count of a returned list if the subroutine is called in a scalar context. This is more efficient than returning all the values in the list and then counting them – passing back one scalar is simpler when that is all the calling context actually requires.

Perl allows subroutines to directly access this information with the wantarray function. Using wantarray allows us to intelligently return different values based on what the caller wants. For example, we can return a list either as a reference or a list of values, depending on the way in which we were called:

return wantarray? @files: \@files;

We can also use wantarray to return undef or an empty list depending on context, avoiding the problems of assigning undef to an array variable as we discussed above:

return wantarray? (): undef;

Modifying our original subroutine to incorporate both these changes gives us the following improved version of list_files that handles both scalar and list context:

sub list_files {
  my $path = shift;

  return wantarray? ():undef unless defined $path;
  my @files = glob "$path/ *";
  return wantarray? @files: \@files;
}

This is an example of Perl's reference counting mechanism in action; @files may go out of scope, but the reference returned in scalar context preserves the values it holds.

We can now call list_files with two different results. In list context we get either a list of files, or an empty list if either no files were found, or the path is undefined. This allows the return value to be used in a foreach loop. If we want to distinguish between a defined path with no files and an undefined path we call list_files in scalar context. In return, we get a reference to a list of files, a reference to an empty list if no files were found, or the undefined value if the path was undefined. By additionally testing for the undefined value with defined, we can now distinguish all three cases:

# list context
@files = list_files ($ARGV[0]);
die "No path defined or no files found" unless @files;
print "Found: @files \n";

# scalar context
$files = list_files($ARGV[0]);
die "No path defined! \n" unless defined $files;
die "No files found! \n" unless $files;
print "Found: @{$files} \n";

One final note about wantarray: If we want to find the number of files rather than retrieve a list, then we can no longer call the subroutine in scalar context to achieve it. Instead, we need to call the subroutine in list context and then convert it into a scalar explicitly:

$count = $#{list_files $ARGV[0]}+1;

This is much clearer, because it states that we really do mean to use the result in a scalar context. Otherwise, it could easily be a bug that we have overlooked. However, be very careful not to use scalar here. We often use scalar to count arrays, but scalar forces its argument into a scalar context. $# requires that its argument is a list, and then counts it.

Handling Void Context

So far we have considered list and scalar contexts. If the subroutine is called in a void context that is undefined. We can use this fact to save time computing a return value, or even to produce an error:

sub list_files {
  die "Function called in void context" unless defined wantarray;
  ...
}

Returning the Undefined Value - Page 20
Professional Perl Programming
Handling Context: an Example - Page 22


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