Without running the snippet what does this print:

sub foo { return 'hello' unless $_[0]; } print "First: " . foo(1) . "\n"; print "Second: " . foo(0) . "\n";

I have to admit I did not expect this, I expected to get nothing in the first case, not the value of the condition.

This comes from a test script for XML::Rules in which, in a filter, I had the following code:

my $parser_remove = XML::Rules->new( rules => [ _default => 'raw', line => sub { my ($tag, $attrs, $context, $parents) = @_; if ($attrs->{_content} =~ /\s+NOT\s+/) { $parents->[-2]{_remove} = 1; # skip the <lines> and se +t the attribute directly in <address> } return [$tag => $attrs]; }, address => sub { return $_[0] => $_[1] unless ($_[1]->{_remove}); } ], style => 'filter', );
It should remove all <address> tags that contain a <line> that contains \s+NOT\s+. Instead of just removing the said tags the code replaces them by "1", that is the value of the $_[1]->{_remove}. It did not take long to find the problem in this case, but still I think it's worth noting, in case someone makes the same mistake in a more complex code.

Replies are listed 'Best First'.
Re: Value of a statement with modifier
by davidrw (Prior) on Jan 22, 2007 at 16:56 UTC
    from perlsub: "The return value of a subroutine is the value of the last expression evaluated."

    this is a nice and subtle example (i had to run it too).. $_[0] is the last expression evaluated when the unless fails, so the sub just ends up returning the first argument..

    good example for always using explict returns ...
    return $_[0] ? undef : 'hello'; # or: return 'hello' unless $_[0]; return;

      A small quibble, but I believe the first example should be written as:

      return $_[ 0 ] ? () : 'hello';

      --
      "Go up to the next female stranger you see and tell her that her "body is a wonderland."
      My hypothesis is that she’ll be too busy laughing at you to even bother slapping you.
      " (src)

Re: Value of a statement with modifier
by fergal (Chaplain) on Jan 23, 2007 at 00:14 UTC

    It becomes quite clear when you rewrite it as

    sub foo { if ($_[0]) { return 'hello'; } # go off the end of sub without return so return the last expression }

Re: Value of a statement with modifier (unless)
by tye (Sage) on Jan 22, 2007 at 18:27 UTC

    I've seen this before but it wasn't a big problem because the expression returned was false. The previous examples didn't use unless. So avoiding unless may be one way to avoid this surprise.

    - tye        

      Well, this may actually make it even more problematic. In scalar context it's fine, but in list one you get a one element list, where the value of the element is 0, '' or undef. In either case it was something I did not expect even though I probably should so I thought it's good to post a note.

        Indeed, thanks for posting; I have now modified Perl 6 to fix this problem today--it no longer returns the last expression evaluated, but the value of the last statement in the block. Happily, fixing this (and a few other things) also makes list comprehensions a lot easier to write now.
Re: Value of a statement with modifier
by ambrus (Abbot) on Jan 23, 2007 at 11:38 UTC