http://www.perlmonks.org?node_id=1074441


in reply to Hope a subroutine will return undef by default

Is there a difficulty or problem with having an explicit return in your subroutine? That is a standard practice for me and I reject any code (in code reviews) that doesn't do so.

Keep in mind that return undef; is not the same as return; and it can lead to some unwanted pain and grief if that is not understood.

Update: You can find a good discussion about the difference between the two here: https://www.securecoding.cert.org/confluence/display/perl/EXP00-PL.+Do+not+return+undef

It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.

Replies are listed 'Best First'.
Re^2: Hope a subroutine will return undef by default
by choroba (Cardinal) on Feb 11, 2014 at 16:50 UTC
    Before you made the update, I prepared a short demonstration of the difference:
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; sub explicit { return undef } sub bare { return } print "Explicit: ", Dumper [ explicit() ]; print "Bare: ", Dumper [ bare() ];

    Output:

    Explicit: $VAR1 = [ undef ]; Bare: $VAR1 = [];
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Good demo! I didn't see it when adding the update. :( On the other hand, it's hard to have too many examples/discussions on how context can come into play in unexpected ways.

      It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
Re^2: Hope a subroutine will return undef by default
by Anonymous Monk on Feb 11, 2014 at 17:00 UTC

    From above cert.org link ...

    In list context, things are slightly more complicated. An empty list, when evaluated in a boolean condition, evaluates to false. But the value undef, when evaluated in list context, evaluates to true because it is converted to a list with the singleton value undef. Therefore, a function should not return undef if it might ever be invoked in list context.

    ... that very thing -- an empty list collapsing to nothing -- has caused me irritation to work around it when something is expected, even undef: by calling the offending code in scalar context. And that was/is the *only* purpose of that damn separate call. I absolutely hate context based returned values in such cases.

      But the value undef, when evaluated in list context, evaluates to true because it is converted to a list with the singleton value undef. Therefore, a function should not return undef if it might ever be invoked in list context.

      Utter nonsense!

      "In list context" is almost the opposite of "evaluate to a boolean value". Probably the only tiny grain of truth to that is how "list assignment in scalar context" evaluates to the size of the right-hand list so "return;" is required to exit a loop written like:

      while( my( $garthok ) = narfle() ) {

      But, of course, you can write (and are more likely to write) that loop like:

      while( my $garthok = narfle() ) {

      Functions that return more than one value or already return a variable number of values should indeed return an empty list when wanting to convey "false". Functions that only ever return a single value, should usually "return undef;" or "return 0;" rather than be transformed into functions that return a variable number of values.

      IME, you are much more likely to get bitten by a "get a scalar" function returning an empty list in lots of different types of code like:

      my %hash = ( gnarfle => get1garthok(), tool => a_herring() ); feed( get1garthok(), a_herring(), $spoon );

      than to get bitten by deciding to uselessly use a list assignment directly in a conditional expression when dealing with a "get a scalar" function.

      Note how the exact problem with doing what the quoted text suggests is that it can easily screw you up when you call it in list context (the opposite of what they claim).

      Now, if you want to be able to distinguish "successfully return 'undef'" from "failure which returns nothing", then you might opt for "return;" for the latter case (and you'll have to be extra careful when using such a function).

      - tye