Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday December 15, 2006
01:50 PM

Returning 'false' (sometimes)

[ #31925 ]

In code which sometimes returns 'false', I keep seeing code like the following:

sub foo {
  return undef unless bar(@_);   # or 'return 0;'
  return $something_else;
}

That behavior needs to be documented very carefully as it has a subtle bug which people keep stumbling over. Most of the time it works:

if ( my $result = foo() ) { ... }

But what if, for example, you want to accumulate results so you decide to use an array?

if ( my @results = foo() ) { ... }

Congrats! If &foo return false, you now have a one-element array which, in this context, evaluates as true. This is very likely a bug. You can accomplish the same thing, probably bug free, if you just use a bare return:

sub foo {
  return unless bar(@_);
  return $something_else;
}

From perldoc -f return:

If no EXPR is given, returns an empty list in list context, the undefined value in scalar context, and (of course) nothing at all in a void context.

In other words, if you wish to return 'false', a bare return will Do The Right Thing.

The only significant objection this I can recall hearing is the following:

if ( some_func(1, foo(), 2) ) { ... }

Because that's in list context, if &foo has a bare return, &foo returns the empty list and &some_func receives (1, 2). I don't see this happening too often, but you can get around it by forcing scalar context.

if ( some_func(1, scalar foo(), 2) ) { ... }

Now &some_func will receive (1, undef, 2).

Also, if you're returning from a ternary operator, you can get the same behavior with this:

return $some_val ? $some_val : ();

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • We recently hit against a bug with this the opposite way round. The JSON [cpan.org] module's objToJson function takes a Perl data structure and returns a Json string representation of it. But if the input is undef then it uses bare return.

    The bug was that this return value was being used in the parameter list of another function, and the bare return meant there was a argument missing.

    Once we'd spotted the bug it was simple to put scalar before the call to objToJson, but it was subtle. If a function is documen

  • Damian Conway made a similarly convincing argument in Perl Best Practices. This practice be enforced with Subroutines::ProhibitExplicitReturnUndef [cpan.org] policy in Perl::Critic.