Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Hope a subroutine will return undef by default

by qj1020 (Initiate)
on Feb 11, 2014 at 16:21 UTC ( #1074436=perlquestion: print w/ replies, xml ) Need Help??
qj1020 has asked for the wisdom of the Perl Monks concerning the following question:

I know it's a little weird, but I would like to have my subroutines to return undef if there is no explicit "return ..." statement inside the subroutine.

Currently perl will return the last values that this routine sees, defeating the logic of one of the key caller functions.

wonder if there is a way to force to return undef by default

Thanks in advance,

Comment on Hope a subroutine will return undef by default
Re: Hope a subroutine will return undef by default
by hdb (Parson) on Feb 11, 2014 at 16:28 UTC

    You could make undef; the last statement in each of your functions...

Re: Hope a subroutine will return undef by default
by wjw (Deacon) on Feb 11, 2014 at 16:33 UTC
    Interesting question... will have to try this out.

    call_sub; my $what_do_I_get = sub { return undefined; }

    From The Docs

    ...You can omit the EXPR, in which case nothing is undefined, but you still get an undefined value that you could, for instance, return from a subroutine, assign to a variable, or pass as a parameter. ...

    Not sure if one could make that the default though..?!?

    ...the majority is always wrong, and always the last to know about it...
    Insanity: Doing the same thing over and over again and expecting different results.
Re: Hope a subroutine will return undef by default
by LanX (Canon) on Feb 11, 2014 at 16:34 UTC
    there is no pragma to do this.

    A naked return; at the end is IMHO the best workaround.

    Of course one could write a module which parses all functions during one of the BEGIN-phases and wraps a naked return if there is no return as final statement, but this is IMHO far too vulnerable for production. ( update and wouldn't work for dynamically defined functions)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    ) It returns an empty list in list context which produces an undef in scalar context.

      I'm starting to prefer simply adding this to the end of the sub:

      ();
      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
        well if you really wanna "golf" better skip the semicolon and safe 33% of the necessary characters. ;-)

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: Hope a subroutine will return undef by default
by boftx (Chaplain) on Feb 11, 2014 at 16:35 UTC

    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.
      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.

      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        

Re: Hope a subroutine will return undef by default
by Anonymous Monk on Feb 11, 2014 at 16:37 UTC

    With sub rewriting, via attributes at least, you could arrange the sub to return undef: http://perltv.org/v/code-attributes presentation about code attributes by Steve B (video; via https://twitter.com/PerlWeekly). (Blame PerlMonks for links being just dead text.)

      Put your links into square brackets and they become alive...

        I did that first, with variations; got "Permission denied ... [Tt]ough beans". >-/

      Thanks to you all for replying and giving me some thoughts. Will check out the link of the youtube video when I get more time.

      Here is more of the context: the subroutines (in the form of strings) was sent to my server on the fly for execution by a function under my control. I wish I can go and change the source of the subroutines to add an explicit "return undef" (the function is executed on my side in scalar context, so it's ok) but I can't. I am thinking of modifying the incoming subroutines, if it doesn't have a "return undef" before the ending of the subroutine, I will add one. But it's not elegant.

Re: Hope a subroutine will return undef by default
by Jenda (Abbot) on Feb 11, 2014 at 23:58 UTC

    What if instead of trying to bend Perl to be like ... well ... what language are you actually trying to mimic here? ... what if instead you just got used to Perl being Perl? I can understand a code policy requiring an explicit return statement ensured either by code review or (if such thing is possible) using Perl::Critic, but no matter what way you do it this is only ever gonna cause confusion and pain. I'm pretty sure you could do something using source code filters or somesuch hackery, but you really do not want to do that!

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

      > what language are you actually trying to mimic here?

      At least Javascript comes to mind (update: and Python)

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        You are right, javascript does this. "return ;" in the middle of a function has the same return value as the case when execution of the function goes the end of the function body without a return statement --- both cases return "undefined" or null. No surprises.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1074436]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2014-07-23 21:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (152 votes), past polls