Re: Hope a subroutine will return undef by default
by boftx (Deacon) 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.
| [reply] [d/l] [select] |
|
|
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 = [];
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
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.
| [reply] |
|
|
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).
| [reply] [d/l] [select] |
Re: Hope a subroutine will return undef by default
by LanX (Saint) 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. | [reply] [d/l] [select] |
|
|
();
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
| [reply] [d/l] |
|
|
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)
| [reply] |
|
|
|
|
|
|
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.
| [reply] |
|
|
| [reply] |
|
|
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.
| [reply] |
Re: Hope a subroutine will return undef by default
by hdb (Monsignor) on Feb 11, 2014 at 16:28 UTC
|
| [reply] |
Re: Hope a subroutine will return undef by default
by wjw (Priest) 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.
| [reply] [d/l] |
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.)
| [reply] |
|
|
| [reply] |
|
|
| [reply] |
|
|
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.
| [reply] |