Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

[SOLVED] Return statement in subroutine(s) is necessary when not returning anything?

by thanos1983 (Parson)
on Nov 02, 2015 at 22:08 UTC ( [id://1146764]=perlquestion: print w/replies, xml ) Need Help??

thanos1983 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

Well usually I am using the return statement to return either a scalar, array, hash etc. I am just wondering in cases such as the example bellow. There is nothing returning by the subroutine, so all the local variables in the subroutine will size to exist as soon as the subroutine will reach the end.

Sample code:

#!/usr/bin/perl use strict; use warnings; sub subroutineWithReturnStatement { print shift; } subroutineWithReturnStatement("First Sample String as Input\n"); sub subroutineWithNoReturnStatement { print shift; return; } subroutineWithNoReturnStatement("Second Sample String as Input\n"); __DATA__ First Sample String as Input Second Sample String as Input

From the perlsub->DESCRIPTION documentation I found the following part:

A return statement may be used to exit a subroutine, optionally specifying the returned value, which will be evaluated in the appropriate context (list, scalar, or void) depending on the context of the subroutine call. If you specify no return value, the subroutine returns an empty list in list context, the undefined value in scalar context, or nothing in void context. If you return one or more aggregates (arrays and hashes), these will be flattened together into one large indistinguishable list. If no return is found and if the last statement is an expression, its value is returned. If the last statement is a loop control structure like a foreach or a while , the returned value is unspecified. The empty sub returns the empty list.

So my question is, is there any difference in using return statement if there is nothing to return from a subroutine?

Update: based on replies of stevieb and Anonymous cleared out that is better to implicitly use a return; statement to clearly show where your subroutine ends and also to avoid implicit return data.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: Return statement in subroutine(s) is necessary when not returning anything?
by stevieb (Canon) on Nov 02, 2015 at 22:16 UTC
    There is always something to return from a sub (in some cases, even  undef); if no  return() is explicitly stated, it'll return the value of the last expression evaluated implicitly. It'll do this even if the sub is empty. A return even if you return void (nothing) is one way to show that you specifically mean to exit it, whether due to a condition, or to emphasize where the end of your sub is supposed to be. Sometimes it's handy to say  if ! defined sub();

      Hello stevieb,

      Thank you for your time and effort reading and replying to my question. Well yeah you are right, it is easier and better way of coding to place a return; (void) to show that your subroutine ends there.

      But also as Anonymous pointed out, it is better to return (void) instead of implicit return.

      That been said I have my answer to my question. Thank you for your time and effort it helped to clear out my thought.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        Yes, explicit return with void is better than implicit return. It makes your API more reliable. Later tonight I'll dig up and update this post as to why explicit exits are important as well...
Re: Return statement in subroutine(s) is necessary when not returning anything?
by Anonymous Monk on Nov 02, 2015 at 22:56 UTC
    There is nothing returning by the subroutine

    Yes, in your first example there is - it's the return value of the print, as per the piece of documentation you quoted ("If no return is found and if the last statement is an expression, its value is returned.").

    Note that Perl::Critic / PBP has this to say about the issue:

    Subroutines without explicit return statements at their ends can be confusing. It can be challenging to deduce what the return value will be.

    Furthermore, if the programmer did not mean for there to be a significant return value, and omits a return statement, some of the subroutine's inner data can leak to the outside. Consider this case:

    package Password; # every time the user guesses the password wrong, its value # is rotated by one character my $password; sub set_password { $password = shift; } sub check_password { my $guess = shift; if ($guess eq $password) { unlock_secrets(); } else { $password = (substr $password, 1).(substr $password, 0, 1); } } 1;

    In this case, the last statement in check_password() is the assignment. The result of that assignment is the implicit return value, so a wrong guess returns the right password! Adding a `return;' at the end of that subroutine solves the problem.

    The example is a little contrived, but another argument I have read about implicit returns is this: If you don't specify an explicit return, the users of your module's API may get used to your sub returning a value, for example they may assume that like many Perl functions a true value indicates success, and if their code starts relying on that, they may be surprised when your code, which never intended to return any value, suddenly changes its behavior. Another viewpoint: An explicit return tells whomever is reading your code that yes, you did intend to return exactly that value.

    A common counter-argument is "but I know I'm only ever calling this sub in void context", which certainly can be true - until someone else starts working with your code :-)

    Having said all that, I've used the implicit return plenty of times, but usually only for brevity, as in when I'm writing a 1-to-3 line sub that I want to keep short. Otherwise I tend to agree with Perl::Critic that it's better to be explicit, and that includes return; for when I don't want my sub to return anything; I can always update the API later and add a useful return value.

      P.S. Another argument for an explicit return:

      sub foo { print "I am foo\n"; bar(); }

      Can you tell me what context the call to bar() is in? Nope, not from this code! (Answer: It's the same context as foo is called in.) There is a discussion in this thread.

      Hello Anonymous,

      Thank you for your time and effort, reading and writing this analytical reply to my question.

      You are absolutely right: Subroutines without explicit return statements at their ends can be confusing. It can be challenging to deduce what the return value will be. Furthermore, if the programmer did not mean for there to be a significant return value, and omits a return statement, some of the subroutine's inner data can leak to the outside.

      Well without any question I would recommend to use return; even if the statement returns void. Not only to indicate that the subroutine ends at this point but also to avoid data leakage.

      Again thank you for your time and effort.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: [SOLVED] Return statement in subroutine(s) is necessary when not returning anything?
by ikegami (Patriarch) on Nov 03, 2015 at 13:29 UTC

    based on replies of stevieb and Anonymous cleared out that is better to implicitly use a return; statement to clearly show where your subroutine ends and also to avoid implicit return data.

    If it's true that the trailing return; is better, why does practically noone use it?

      Well, whilst I hesitate to say it, there are a few places where perl lets people get away with shoddy coding practices...

        I disagree. A large part of my affection for Perl is its terseness. It doesn't force you to do things that are obvious enough for the compiler so obvious enough for a good dev. Verbosity can be an impediment to communication; especially in technical matters. Back to the OP's example–

        sub ohai { print "OHAI"; return; }

        That is technically "wrong." It prevents you from being able to use the sub like this do_something() if ohai(); It makes the sub less useful (Update: and harder to test). To fix that, you would report on success. That RFC:SHOULD look like:

        sub ohai { return print "ohai"; }

        How good a practice does that appear to be? Looks foolish to me. I much prefer the implicit return (when it's sensible, it's not always) than the explicit being recommended.

        I didn't say a few people don't use the practice. In fact, I don't think I've come across any CPAN code that uses the practice. Claims of shoddiness seem to be *greatly* exaggerated.
Re: Return statement in subroutine(s) is necessary when not returning anything?
by Anonymous Monk on Nov 02, 2015 at 22:19 UTC

    So my question is, is there any difference in using return statement if there is nothing to return from a subroutine?

    Try it and see what happens, Basic debugging checklist , Data::Dump::dd()

    using return ensures return gets to do what it does, not using return leaves it up to implicit return

      Hello Anonymous,

      Thank you for your time and effort reading and replying to my question. You are absolutely right, it is easier and better way of coding to place a return; (void) to show that your subroutine ends there and also to avoid and implicit return case.

      Thank you again for your time and effort.

      Seeking for Perl wisdom...on the process of learning...not there...yet!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1146764]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (7)
As of 2024-04-19 12:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found