Closed p5pRT closed 13 years ago
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful.
(Actually\, it seems that anything can be passed the return value of return.
C\
Nicholas Clark
* Nicholas Clark \perlbug\-followup@​perl\.org [2008-06-20 18:00]:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error?
Because `return` is a function\, not a statement\, presumably so you can write the following?
sub process_file { # ... open my $fh\, '\<'\, $fn or return; # ... }
-- *AUTOLOAD=*_;sub _{s/(.*)::(.*)/print$2\,("\,$\/"\," ")[defined wantarray]/e;$1} &Just->another->Perl->hack; #Aristotle Pagaltzis // \<http://plasmasturm.org/>
The RT System itself - Status changed from 'new' to 'open'
On Fri\, Jun 20\, 2008 at 08:04:27AM -0700\, Nicholas Clark wrote:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful. (Actually\, it seems that anything can be passed the return value of return. C\
works just fine).
It seems to me that there's lots of useless code that nonetheless isn't a syntax error... :)
Perhaps that construct could generate a warning. Personally\, I wouldn't expect it to be a syntax error.
(Note that return can be usefully used as an expression: my $foo = $bar ? return : 'baz'; Odd\, but it works.)
Ronald
2008/6/20 via RT Nicholas Clark \perlbug\-followup@​perl\.org:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful. (Actually\, it seems that anything can be passed the return value of return. C\
works just fine).
return is technically parsed as a list operator (LSTOP). That enables using it in compound expressions.
Note that this syntax works also for other control flow statements :
$ perl -wle '$i=3;while(1){print($i--||last)}' 3 2 1
I don't really see a reason to change it.
On Fri\, Jun 20\, 2008 at 12:06:31PM -0400\, Ronald J Kimball wrote:
(Note that return can be usefully used as an expression: my $foo = $bar ? return : 'baz'; Odd\, but it works.)
But then people start writing code that looks like this:
$basket->calculate() or return $self->emit("Could not recalculate"\, 'error') if $basket->complete();
and I go http://www.flickr.com/photos/twoshortplanks/28698637/
(sadly I no longer have the other example of code from the same author\, that mixed declaration\, conditional initialisation and control flow in one statement. But actually\, I don't think that he was using ternaries in either)
On Fri\, Jun 20\, 2008 at 06:29:45PM +0200\, Rafael Garcia-Suarez wrote:
return is technically parsed as a list operator (LSTOP). That enables using it in compound expressions.
Note that this syntax works also for other control flow statements :
$ perl -wle '$i=3;while(1){print($i--||last)}' 3 2 1
I don't really see a reason to change it.
Ah. Makes sense. I guess I can reject my own bug.
Nicholas Clark
On 6/20/08\, Nicholas Clark \nick@​ccl4\.org wrote:
Ah. Makes sense. I guess I can reject my own bug.
alternately\, restyle it as a wishlist item\, the wish being for general "code unreachable" warnings.
On Fri\, June 20\, 2008 10:54 am\, David Nicol wrote:
On 6/20/08\, Nicholas Clark \nick@​ccl4\.org wrote:
Ah. Makes sense. I guess I can reject my own bug.
alternately\, restyle it as a wishlist item\, the wish being for general "code unreachable" warnings.
which return(return) would trigger but return($x || return) would not
* Yitzchak Scott-Thoennes \sthoenna@​efn\.org [2008-06-20 20:00]:
On Fri\, June 20\, 2008 10:54 am\, David Nicol wrote:
alternately\, restyle it as a wishlist item\, the wish being for general "code unreachable" warnings.
which return(return) would trigger but return($x || return) would not
Which would be as it would have should been[1]\, because in those cases where $x is true\, the outer `return` will indeed be reached.
[1]: Tip of the hat to a certain crazy Aussieâs keynote.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
On 6/20/08\, Yitzchak Scott-Thoennes \sthoenna@​efn\.org wrote:
general "code unreachable" warning
which return(return) would trigger but return($x || return) would not
but
my $x=0; return($x || return)
would\, if we can apply used-as-lvalue analysis to constant folding
(ivory-tower to the point of being off-topic)
On Friday 20 June 2008 21:20:54 David Nicol wrote:
On 6/20/08\, Yitzchak Scott-Thoennes \sthoenna@​efn\.org wrote:
general "code unreachable" warning
which return(return) would trigger but return($x || return) would not
but
my $x=0; return($x || return)
would\, if we can apply used-as-lvalue analysis to constant folding
(ivory-tower to the point of being off-topic)
Why not add rules to Perl::Critic to catch these?
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too. "$x" works just as fine as "return $x" and is potential faster:
$ perl -MO=Concise -wle 'return 1;' 6 \<@> leave[1 ref] vKP/REFC ->(end) 1 \<0> enter ->2 2 \<;> nextstate(main 1 -e:1) v ->3 5 \<@> return K ->6 3 \<0> pushmark s ->4 4 \<$> const[IV 1] s ->5 -e syntax OK $ perl -MO=Concise -wle '1;' 3 \<@> leave[1 ref] vKP/REFC ->(end) 1 \<0> enter ->2 2 \<;> nextstate(main 1 -e:1) v ->3 - \<0> ex-const v ->3 -e syntax OK
The only thing that speaks for return is that it "speaks" e.g. looks more nice to the human reader.
All the best\,
Tels
-- Signed on Fri Jun 20 21:57:22 2008 with key 0x93B84C15. Get one of my photo posters: http://bloodgate.com/posters PGP key on http://bloodgate.com/tels.asc or per email.
"Sundials don't work\, the one I've had in my basement hasn't changed time since I installed it." grub (11606) on 2004-12-03 on /.
The only thing that speaks for return is that it "speaks" e.g. looks more nice to the human reader Also for breaking out from a subroutine before its natural end.
On Saturday 21 June 2008 11:05:17 Vincent Pit wrote:
The only thing that speaks for return is that it "speaks" e.g. looks more nice to the human reader
Also for breaking out from a subroutine before its natural end.
Of course :) I was talking about the usual case at the very end\, e.g.
sub foo { my $x = shift;
my $y = $x + 1; return $x; # superflous return }
:)
All the best\,
Tels
-- Signed on Sat Jun 21 12:25:23 2008 with key 0x93B84C15. View my photo gallery: http://bloodgate.com/photos PGP key on http://bloodgate.com/tels.asc or per email.
"I can imagine what you're thinking though: this girl keeps her brains in her backside! But actually only the more primitive parts of my brain are in my butt. The more interesting parts are kept in a PC - my spinal cord is actually an RS232 lead!"
-- Lucy\, the OrangUtan Robot Girl http://tinyurl.com/3fv6z
Tels wrote:
On Saturday 21 June 2008 11:05:17 Vincent Pit wrote:
The only thing that speaks for return is that it "speaks" e.g. looks more nice to the human reader Also for breaking out from a subroutine before its natural end.
Of course :) I was talking about the usual case at the very end\, e.g.
sub foo \{ my $x = shift; my $y = $x \+ 1; return $x; \# superflous return \}
Let me be devils advocate. But this function seems it all superflous :) Isn't it just the ID function? :)
OK\, OK :-P -- Alberto SimÔes - Departamento de Informåtica - Universidade do Minho Campus de Gualtar - 4710-057 Braga - Portugal
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-20 23:05]:
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too.
Programs should be written for people to read and only incidentally for machines to execute.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
Tels wrote:
sub foo { my $x = shift; my $y = $x + 1; return $x; # superflous return }
A slightly less innocent variant:
$ perl -MData::Dumper -wle'
sub foo { my $y = $_[0] + 1; return $_[0]; } my $v = "0"; print Dumper($v); foo($v); print Dumper($v); ' $VAR1 = '0';
$VAR1 = 0;
(Data::Dumper prefers to show an IV above a PV)
-- Affijn\, Ruud
"Gewoon is een tijger."
On Saturday 21 June 2008 13:22:59 Aristotle Pagaltzis wrote:
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-20 23:05]:
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too.
Programs should be written for people to read and only incidentally for machines to execute.
With the current state of abundand hardware power\, it should be no problem to show the human a "human-readable" version of the program and let the machine execute the "machine-readable" version.
Which\, btw\, happens\, anyway. :)
So the editor could colorize it\, pretty-print it\, add return statements and automatic comments.
Which\, btw\, happens for most people\, anyway. :)
All the best\,
Tels
-- Signed on Sat Jun 21 13:33:56 2008 with key 0x93B84C15. Get one of my photo posters: http://bloodgate.com/posters PGP key on http://bloodgate.com/tels.asc or per email.
"Retsina?" - "Ja\, Papa?" - "Schach Matt." - "Is gut\, Papa."
On Saturday 21 June 2008 13:34:11 Dr.Ruud wrote:
Tels wrote:
sub foo { my $x = shift; my $y = $x + 1; return $x; # superflous return }
A slightly less innocent variant:
My example above was wrong\, I meant "return $y".
To make it clear:
sub foo { .... return $foo; # superflous return\, could be just $foo }
All the best\,
Tels
-- Signed on Sat Jun 21 13:47:08 2008 with key 0x93B84C15. View my photo gallery: http://bloodgate.com/photos PGP key on http://bloodgate.com/tels.asc or per email.
"Ein Vorschlag\, das Grundgesetz zu modifizieren\, ist kein Anschlag auf die Verfassung."
-- GĂŒnther Beckstein
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-21 14:05]:
On Saturday 21 June 2008 13:22:59 Aristotle Pagaltzis wrote:
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-20 23:05]:
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too.
Programs should be written for people to read and only incidentally for machines to execute.
With the current state of abundand hardware power\, it should be no problem to show the human a "human-readable" version of the program and let the machine execute the "machine-readable" version.
Which\, btw\, happens\, anyway. :)
So the editor could colorize it\, pretty-print it\, add return statements and automatic comments.
Which\, btw\, happens for most people\, anyway. :)
How can syntax highlighters infer unwritten programmer intent?
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
On Saturday 21 June 2008 15:01:40 Aristotle Pagaltzis wrote:
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-21 14:05]:
On Saturday 21 June 2008 13:22:59 Aristotle Pagaltzis wrote:
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-20 23:05]:
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too.
Programs should be written for people to read and only incidentally for machines to execute.
With the current state of abundand hardware power\, it should be no problem to show the human a "human-readable" version of the program and let the machine execute the "machine-readable" version.
Which\, btw\, happens\, anyway. :)
So the editor could colorize it\, pretty-print it\, add return statements and automatic comments.
Which\, btw\, happens for most people\, anyway. :)
How can syntax highlighters infer unwritten programmer intent?
I dunno. But they make the code easier to read for humans.
All the best\,
Tels
-- Signed on Sat Jun 21 15:45:27 2008 with key 0x93B84C15. Get one of my photo posters: http://bloodgate.com/posters PGP key on http://bloodgate.com/tels.asc or per email.
"Sacrificing minions: Is there any problem it CAN'T solve?"
-- Lord Xykon
On Sat\, Jun 21\, 2008 at 8:01 AM\, Aristotle Pagaltzis \pagaltzis@​gmx\.de wrote:
How can syntax highlighters infer unwritten programmer intent?
Such syntax highlighting systems are easy to find\, but you have to pay them by the hour
Aristotle Pagaltzis wrote:
* Tels \nospam\-abuse@​bloodgate\.com [2008-06-20 23:05]:
Also\, I'd like to add that "return" at the end of a function is almost always pointless\, too.
Programs should be written for people to read and only incidentally for machines to execute.
If your suggestion is that "return" improves readability\, I disagree that the addition of "return" will universally improve the ability for a person to read the code. The "return" is more than just verbosity - it is a different statement with different behaviour.
Perl programmers *must* be accustomed to code blocks returning the last value. This is how grep and map work. Any Perl programmer that cannot read this comfortably will have problems with these basic functions. If the programmer needs an explicit "return" to tell them what is happening\, I would suggest it isn't about machine vs people but Perl vs C/Java.
Cheers\, mark
P.S. That said - there are a lot of C/Java programmers out there\, and I've been forced to use 'return' more liberally throughout my code\, as the C/Java programmers just don't seem to be able to get it...
-- Mark Mielke \mark@​mielke\.cc
On Sunday 22 June 2008 16:08:22 Mark Mielke wrote:
Perl programmers *must* be accustomed to code blocks returning the last value. This is how grep and map work. Any Perl programmer that cannot read this comfortably will have problems with these basic functions. If the programmer needs an explicit "return" to tell them what is happening\, I would suggest it isn't about machine vs people but Perl vs C/Java.
I don't know about your code\, but my map and grep blocks tend to be much shorter than my functions and methods -- shorter even than my for and while loop blocks (which don't explicitly return anything).
-- c
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 01:10]:
If your suggestion is that "return" improves readability\, I disagree that the addition of "return" will universally improve the ability for a person to read the code.
As long as you have the discipline to always\, *always* write a bare `return;` in functions that are meant not to return a value\, and the maintenance programmer who comes after knows of your discipline in that matter\, then using `return` when you do mean to return a value is not necessary.
For everyone else\, putting in an explicit `return` is a way to state explicitly that âyes\, I really did mean for this value to be returned\, I did not just forget to suppress it.â
Perl programmers *must* be accustomed to code blocks returning the last value. This is how grep and map work. Any Perl programmer that cannot read this comfortably will have problems with these basic functions. If the programmer needs an explicit "return" to tell them what is happening\, I would suggest it isn't about machine vs people but Perl vs C/Java.
It is never ever a concern of mine to make code readable to people who are unfamiliar with the language. What concerns me is how to communicate intent to subseqent readers of the code.
My point is about the situation in which a maintenance programmer (or worse\, an API client programmer working on a different module) finds a 10-line function that contains no `return`\, especially if the return value is not used anywhere yet: now s/he has to wonder whether that return value is part of its public interface or not. If you put in an explicit `return`\, there is no doubt about what you meant.
As far as `map` and friends are concerned\, if your blocks are much longer than two simple statements\, you should usually reconsider readability. (Along the same line\, I occasionally write single-expression functions (that go on a single line and donât even unpack their @_)\, and sure\, I omit the `return` in those.)
As I said above\, in theory it is enough to use an explicit `return` to suppress leaking last value from the function in cases where its public interface does not include any return value. But that presumes that you and everyone else who works on the codebase will have perfect discipline about this issue\, *and* that this is known among everyone who works on the codebase.
So putting in an explicit `return` should be your default\, and deviations from that rule should be individually considered.
Not because of what the machine will do\, but because of what it signifies to subsequent readers about what you meant to happen.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
First\, it should be understood by all that this question is really about STYLE - not about universal readability. There are different answers\, and there are different opinions. People who come from a LISP background may find it easier to read one style than people from a C background. Therefore\, for anybody to claim that one is universally easier to read than another is FALSE. It can only be easier to read for a section of the population. As to which section of the population is bigger? ...
Aristotle Pagaltzis wrote:
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 01:10]:
If your suggestion is that "return" improves readability\, I disagree that the addition of "return" will universally improve the ability for a person to read the code.
As long as you have the discipline to always\, *always* write a bare `return;` in functions that are meant not to return a value\, and the maintenance programmer who comes after knows of your discipline in that matter\, then using `return` when you do mean to return a value is not necessary.
There are alternatives. For example\, most people end their modules with "1;" effectively saying "return 1;". In my case\, I have had functions such as you describe with:
sub NAME { ... lots of code ...
undef; }
This is similarly "clear". My function always returns "undef". This is the same clarity as "1;" at the end of the module. The extra blank line makes it very clear to anybody except those people that do not realize that Perl works this way\, and these people really should be trained to recognize this.
For everyone else\, putting in an explicit `return` is a way to state explicitly that âyes\, I really did mean for this value to be returned\, I did not just forget to suppress it.â
See above. There are alternative ways to do this. I'll often do:
sub NAME { ... declarations ...
... bodies ...
$result; }
Another common bit of code that I've written is:
sub foo { my($this) = @_; exists($this->{'foo'}) ? $this->{'foo'} : do { ... expensive calculations ... $this->{'foo'} = ...; }; }
This introduces the other statement that is frequently used to return the last value without a return - do{}. The above code is not significantly improved by adding return anywhere. Perhaps pedantic people with a C background will prefer to see a return statement\, but it is not necessary.
Perl programmers *must* be accustomed to code blocks returning the last value. This is how grep and map work. Any Perl programmer that cannot read this comfortably will have problems with these basic functions. If the programmer needs an explicit "return" to tell them what is happening\, I would suggest it isn't about machine vs people but Perl vs C/Java.
It is never ever a concern of mine to make code readable to people who are unfamiliar with the language. What concerns me is how to communicate intent to subseqent readers of the code.
I agree - what we disagree with is whether an explicit 'return' successfully communicates intent in any way more than an extra pair of parens would. For example\, I often see people doing:
statement if (condition);
Those last parens are not required. If I ask people why they put them\, they tell me that it is to communicate precedence to the user. I strongly disagree - by dumbing down the language by making every precedence explicit\, the result is programmers who do not understand the language\, which might mean they understand your code today\, but not understand somebody else's code tomorrow. "I thought you needed extra parens?" or "I thought you needed a return?" - "what made you think that?" - "Aristotle's code uses it all the time and he knows what he is doing" - "yes\, he does - he's dumbing it down for you." :-)
My point is about the situation in which a maintenance programmer (or worse\, an API client programmer working on a different module) finds a 10-line function that contains no `return`\, especially if the return value is not used anywhere yet: now s/he has to wonder whether that return value is part of its public interface or not. If you put in an explicit `return`\, there is no doubt about what you meant.
Why wasn't the code properly documented? Maintenance is a big program\, and unecessary "return" statements cannot be your fallback. :-)
As far as `map` and friends are concerned\, if your blocks are much longer than two simple statements\, you should usually reconsider readability. (Along the same line\, I occasionally write single-expression functions (that go on a single line and donât even unpack their @_)\, and sure\, I omit the `return` in those.)
Yes\, readability should be considered. However\, there are many ways to solve the readability program. Some people might move the code into an outside subroutine. Some people might make liberal use of white spacing. Whichever choice is chosen\, what remains\, is that return *cannot* be using in grep/map/do\, and people who see these statements absolutely must understand that the return value is the result of the last statement. Once they understand this\, extending it to the "1;" at the end of modules\, or the "$result;" at the end of the subroutine is trivial.
As I said above\, in theory it is enough to use an explicit `return` to suppress leaking last value from the function in cases where its public interface does not include any return value. But that presumes that you and everyone else who works on the codebase will have perfect discipline about this issue\, *and* that this is known among everyone who works on the codebase.
So putting in an explicit `return` should be your default\, and deviations from that rule should be individually considered.
Not because of what the machine will do\, but because of what it signifies to subsequent readers about what you meant to happen.
There are lots of things that a pedantic Perl programmer should do - like checking that arguments in my(...) = @_ are all of the expected types\, or always checking the return result of print(). It's not always practical to do this or even necessary. Perl is a dynamic scripting language. That it doesn't support the 'void' return type is not a reason to explicitly return; on every subroutine that does not have a value to return. This would become almost ridiculous for those of us who write many small subroutines instead of a few large subroutines. The documentation says how the API should be used.
That said - the abundance of C/Java programmers who do not even REALIZE that Perl will implicitly return the last statement\, has forced me to compromise on this\, and "dumb down the language" by explicitly using return in more places. I do not agree that this is good - because the only reason it is necessary is because people might be maintaining the code who do not REALLY know Perl. That's scary...
It's enough that I re-wrote one of our happily running servers in Perl in Java. Why? Because they would not be able to maintain the Perl server\, whereas they may be able to maintain the Java server.
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
On Mon\, 23 Jun 2008 09:52:00 -0400\, Mark Mielke \mark@​mark\.mielke\.cc wrote:
First\, it should be understood by all that this question is really about STYLE - not about universal readability. There are different answers\, and there are different opinions. People who come from a LISP background may find it easier to read one style than people from a C background. Therefore\, for anybody to claim that one is universally easier to read than another is FALSE. It can only be easier to read for a section of the population. As to which section of the population is bigger? ...
Aristotle Pagaltzis wrote:
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 01:10]:
If your suggestion is that "return" improves readability\, I disagree that the addition of "return" will universally improve the ability for a person to read the code.
As long as you have the discipline to always\, *always* write a bare `return;` in functions that are meant not to return a value\, and the maintenance programmer who comes after knows of your discipline in that matter\, then using `return` when you do mean to return a value is not necessary.
There are alternatives. For example\, most people end their modules with "1;" effectively saying "return 1;". In my case\, I have had functions such as you describe with:
sub NAME { ... lots of code ...
undef;
}
What if the function can return a list or a scalar? "return" handles that automatically\, undef does not;
BTW I agree with both worlds. In some cases it should suffice to use the last value\, in some cases one should use return for clarity
-- H.Merijn Brand Amsterdam Perl Mongers http://amsterdam.pm.org/ using & porting perl 5.6.2\, 5.8.x\, 5.10.x\, 5.11.x on HP-UX 10.20\, 11.00\, 11.11\, 11.23\, and 11.31\, SuSE 10.1\, 10.2\, and 10.3\, AIX 5.2\, and Cygwin. http://mirrors.develooper.com/hpux/ http://www.test-smoke.org/ http://qa.perl.org http://www.goldmark.org/jeff/stupid-disclaimers/
H.Merijn Brand wrote:
sub NAME { ... lots of code ...
undef;
}
What if the function can return a list or a scalar? "return" handles that automatically\, undef does not;
Hehe - good question. My answer is that it tends not to happen for my style of programming. That is\, a function that returns a list would take the form:
sub NAME { my @results;
... do whatever to @results ...
@results; }
Now\, I do recall it happening once in the past where I found the need to return from @results from inside a conditional - and I think I decided on "return ();" as I found "return;" to not communicate "return an empty list" as explicitly as I wanted. It was an imperfect situation. :-(
BTW I agree with both worlds. In some cases it should suffice to use the last value\, in some cases one should use return for clarity
Agree. I was playing devil's advocate - not intending to say "never ever use return!". I only challenged the claim that one should "always use return!". :-) It came across as dogma like "never use goto!". :-)
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 16:20]:
H.Merijn Brand wrote:
BTW I agree with both worlds. In some cases it should suffice to use the last value\, in some cases one should use return for clarity
Agree. I was playing devil's advocate - not intending to say "never ever use return!". I only challenged the claim that one should "always use return!". :-) It came across as dogma like "never use goto!". :-)
The original position was that Tels said that `return` is always superfluous and often slower\, so I quoted Abelson/Sussman at him.
I donât know where you found any dogma about always using `return` in my mails. My (possibly just as mistaken) impression is that are much more dogmatic about avoiding `return` than I am about using it.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
Quoth mark@mark.mielke.cc (Mark Mielke):
Another common bit of code that I've written is:
sub foo { my($this) = @_; exists($this->{'foo'}) ? $this->{'foo'} : do { ... expensive calculations ... $this->{'foo'} = ...; }; }
This introduces the other statement that is frequently used to return the last value without a return - do{}. The above code is not significantly improved by adding return anywhere.
I disagree. IMHO
sub foo { my ($this) = @_;
exists $this->{foo} and return $this->{foo};
...expensive calculations...
return $this->{foo} = ...; }
is clearer in at least two important ways.
Ben
-- We do not stop playing because we grow old; we grow old because we stop playing. ben@morrow.me.uk
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 15:55]:
Another common bit of code that I've written is:
sub foo { my($this) = @_; exists($this->{'foo'}) ? $this->{'foo'} : do { ... expensive calculations ... $this->{'foo'} = ...; }; }
This introduces the other statement that is frequently used to return the last value without a return - do{}. The above code is not significantly improved by adding return anywhere.
Yes it would. You could lose a level of indentation and it would be much easier to skim if you converted the truth case to a guard clause:
return $this->{ foo } if exists $this->{ foo };
It is never ever a concern of mine to make code readable to people who are unfamiliar with the language. What concerns me is how to communicate intent to subseqent readers of the code.
I agree - what we disagree with is whether an explicit 'return' successfully communicates intent in any way more than an extra pair of parens would. For example\, I often see people doing:
statement if (condition);
Those last parens are not required. If I ask people why they put them\, they tell me that it is to communicate precedence to the user. I strongly disagree - by dumbing down the language by making every precedence explicit\, the result is programmers who do not understand the language\, which might mean they understand your code today\, but not understand somebody else's code tomorrow. "I thought you needed extra parens?" or "I thought you needed a return?" - "what made you think that?" - "Aristotle's code uses it all the time and he knows what he is doing" - "yes\, he does - he's dumbing it down for you." :-)
Btw\, why did you use quotes in `$this->{'foo'}`? Theyâre not required.
Perl is a dynamic scripting language. That it doesn't support the 'void' return type is not a reason to explicitly return; on every subroutine that does not have a value to return. This would become almost ridiculous for those of us who write many small subroutines instead of a few large subroutines.
And those of us who prefer to use guard clauses and not contort subroutines into nested single expressions cannot avoid `return` at all.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
On Mon\, Jun 23\, 2008 at 10:20 AM\, Aristotle Pagaltzis \pagaltzis@​gmx\.de wrote:
And those of us who prefer to use guard clauses and not contort subroutines into nested single expressions cannot avoid `return` at all.
leaving the question\, why doesn't the optimizer get rid of return?
tentative answer: because the optimizer authors didn't get around to it\, seeing once-per-subroutine as not enough savings to justify the effort.
Ben Morrow wrote:
I disagree. IMHO
sub foo \{ my \($this\) = @​\_; exists $this\->\{foo\} and return $this\->\{foo\}; \.\.\.expensive calculations\.\.\. return $this\->\{foo\} = \.\.\.; \}
is clearer in at least two important ways.
I find it amusing that you like to see "return" to clearly express intent to a maintainer\, but don't mind using:
exists $this->{foo} and return $this->{foo};
The "and" in this context to replace:
if (exists $this->{foo}) { return $this->{foo}; }
Is very much a Perl specific thing. It's all about style and what you are comfortable with. You are comfortable with something different. In my Perl style guide that I provide to my people\, I suggest that "or" is allowed but "and" as you have used it is not.
As for your code being clearer in two important ways - it is clearer to *you* in two important ways. For myself\, I find "return ... if" or "... and return" to be un-clear. After all\, unless one looks closely\, one might miss the return altogether. I prefer the one subroutine\, one return as a good policy\, with many smaller subroutines over a few big subroutines.
With that\, I'll leave this thread. I think my intent has been recognized. This is a style issue. There is no right answer.
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
Aristotle Pagaltzis wrote:
Btw\, why did you use quotes in `$this->{'foo'}`? Theyâre not required.
Easy. I don't trust Perl\, and (unfortunately) our code needs to run on Perl 5.004 and before.
If somebody can convince me that all versions of Perl 5.004 and later will ALWAYS treat 'foo' as literal without quotes in this context\, I'll be happy to drop it. It may have been Perl earlier than 5.004 that sometimes did unexpected things with:
$foo{time} = 2;
As it is\, the following fails for me today:
$ perl -e '$f{my-variable} = 1; print "$f{my-variable}\n"' syntax error at -e line 1\, near "my-" syntax error at -e line 1\, near "my-" Execution of -e aborted due to compilation errors.
Probably because the '-' triggers it to run in expression mode. Sometimes we use '-' instead of '_'\, or even a space character or ':' in the key value. These won't work for certain. Better to consistently use quotes everywhere.
Such is my opinion and style. Is it comparable to return vs not? It's similar but not the same. In the case of consistent quoting\, it means I can use all values without worrying about it failing for me one day. In the case of return\, both work fine and will not fail one day.
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
For everyone else\, putting in an explicit `return` is a way to state explicitly that âyes\, I really did mean for this value to be returned\, I did not just forget to suppress it.â
See above. There are alternative ways to do this. I'll often do:
sub NAME { ... declarations ...
\.\.\. bodies \.\.\.
$result; }
IMO the habbit to write
sub foo { ... $bar; }
is only syntax preference of writing
sub foo { ... return $bar; }
.. so I consider both to be exactly the same. On the contrary\, if the following sub:
sub foo { do_something_useful(); }
... happens to return something as a side effect\, this is just a wasted CPU due to mis-optimization\, (fortunately small mis-optimization) \, which happens quite often (unfortunately)
For sure 99\,9% of people do not mean it as sub foo { return do_something_useful(); }
and even if they do\, this *is* a bat habbit because this is a potential pain for future readings of this code\, either by author or maintainer.
Just my RUR0.02
BR\, Vadim.
Ben Morrow schreef:
exists $this\->\{foo\} and return $this\->\{foo\};
I prefer that written as:
return $this->{foo} if exists $this->{foo};
-- Affijn\, Ruud
"Gewoon is een tijger."
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 19:55]:
I don't trust Perl\, and (unfortunately) our code needs to run on Perl 5.004 and before.
How about finding out instead of dumbing the code down to your level of insecurity? :-)
If somebody can convince me that all versions of Perl 5.004 and later will ALWAYS treat 'foo' as literal without quotes in this context\, I'll be happy to drop it. It may have been Perl earlier than 5.004 that sometimes did unexpected things with:
$foo{time} = 2;
Are you sure you donât have that backwards? Because I know that many people get surprised by the *opposite* case\, where they expected the function to be called but it gets interpreted literally as a string instead â eg. here:
use constant BAZ => 'bar; $foo{BAZ} = 'quux';
They expect to find `quux` under the key `bar`\, but instead Perl uses `BAZ` as the literal key.
In any case hash key auto-quoting has never done anything unexpected for me. As long as the key is a valid bareword\, it gets quoted. The rule is very simple and consistent\, and I avoid keys that wonât fit the rule as much as possible so I can avoid the quotes whenever possible.
Better to consistently use quotes everywhere.
Such is my opinion and style. Is it comparable to return vs not? It's similar but not the same. In the case of consistent quoting\, it means I can use all values without worrying about it failing for me one day. In the case of return\, both work fine and will not fail one day.
Itâs not comparable to `return` vs nothing\, but itâs comparable to `WHATEVER if ($cond)` vs `WHATEVER if $cond`\, which is an example you brought up.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 19:45]:
I prefer the one subroutine\, one return as a good policy
Aha\, thatâs why youâre so adamant about this issue. Personally\, I cut my programming teeth on Pascal\, and that put me through enough single-exit control flow gymnastics to last me a lifetime.
Guard clauses for me\, thanks.
Regards\, -- Aristotle Pagaltzis // \<http://plasmasturm.org/>
Aristotle Pagaltzis wrote:
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 19:55]:
I don't trust Perl\, and (unfortunately) our code needs to run on Perl 5.004 and before.
How about finding out instead of dumbing the code down to your level of insecurity? :-)
I can't "find out" every year. TomC wrote a thing about it many years ago the last time I checked and it WAS broken in an earlier version of Perl 5\, although Perl 5.004 seems unafflicted. I've watched people submit patches against exactly this $hash{key} and key => on this very porting list. Now\, my information may be 10 years out of date - that's possible. But\, we still use Perl 5.004\, and that's at least 10 years out of date probably as well? :-)
But you are correct - if it's now safe\, for CERTAIN\, I will happily consider removing it from my own style guide that I provide to others. :-)
If somebody can convince me that all versions of Perl 5.004 and later will ALWAYS treat 'foo' as literal without quotes in this context\, I'll be happy to drop it. It may have been Perl earlier than 5.004 that sometimes did unexpected things with:
$foo{time} = 2;
Are you sure you donât have that backwards? Because I know that many people get surprised by the *opposite* case\, where they expected the function to be called but it gets interpreted literally as a string instead â eg. here:
use constant BAZ => 'bar; $foo\{BAZ\} = 'quux';
Yes I'm sure. Different versions of Perl have done different things. It's possible that everything in the last decade works. My history goes with Perl goes back to around 1992 and conclusions have possibly changed.
Better to consistently use quotes everywhere.
Such is my opinion and style. Is it comparable to return vs not? It's similar but not the same. In the case of consistent quoting\, it means I can use all values without worrying about it failing for me one day. In the case of return\, both work fine and will not fail one day.
Itâs not comparable to `return` vs nothing\, but itâs comparable to `WHATEVER if ($cond)` vs `WHATEVER if $cond`\, which is an example you brought up.
It's close - but where () has absolutely no impact on the statement in the "if" case\, the quotes do have effect. The example of $hash{'my-variable'} vs $hash{my-variable}. Compare this to 'blah if condition' vs 'blah if (condition)'. In the former case it's the difference between working and not. In the latter case\, both work fine.
If you can find a valid expression 'blah' or 'condition' where 'blah if condition' fails where 'blah if (condition)' succeeds\, I will happily concede that they are the same and you are correct. Waiting for you to prove me wrong with held breath. :-)
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
Aristotle Pagaltzis wrote:
* Mark Mielke \mark@​mark\.mielke\.cc [2008-06-23 19:45]:
I prefer the one subroutine\, one return as a good policy
Aha\, thatâs why youâre so adamant about this issue. Personally\, I cut my programming teeth on Pascal\, and that put me through enough single-exit control flow gymnastics to last me a lifetime.
Guard clauses for me\, thanks.
Lucky you. :-)
Cheers\, mark
-- Mark Mielke \mark@​mielke\.cc
On Mon\, June 23\, 2008 1:35 pm\, Mark Mielke wrote:
Yes I'm sure. Different versions of Perl have done different things. It's possible that everything in the last decade works. My history goes with Perl goes back to around 1992 and conclusions have possibly changed.
IIRC\, there was breakage for qv\
There's also the special case of '\, also in both places\, becoming ::.
David Nicol schrieb:
On Mon\, Jun 23\, 2008 at 10:20 AM\, Aristotle Pagaltzis \pagaltzis@​gmx\.de wrote:
And those of us who prefer to use guard clauses and not contort subroutines into nested single expressions cannot avoid `return` at all.
leaving the question\, why doesn't the optimizer get rid of return?
tentative answer: because the optimizer authors didn't get around to it\, seeing once-per-subroutine as not enough savings to justify the effort.
The optimizer does something with the op_type OP_RETURN. The ck_return() does change all kids to OP_LEAVESUBLV if lvalue'd. The problem is the tokenizer.
Concise does not help - identical results. $ perl5.11.0d -MO=Concise\,-exec -e'sub foo {return return}; foo' 1 \<0> enter 2 \<;> nextstate(main 2 -e:1) v:{ 3 \<0> pushmark s 4 \<#> gv[*foo] s 5 \<1> entersub[t2] vKS/TARG\,1 6 \<@> leave[1 ref] vKP/REFC
$ perl5.11.0d -MO=Concise\,-exec -e'sub foo {return}; foo' 1 \<0> enter 2 \<;> nextstate(main 2 -e:1) v:{ 3 \<0> pushmark s 4 \<#> gv[*foo] s 5 \<1> entersub[t2] vKS/TARG\,1 6 \<@> leave[1 ref] vKP/REFC
At least -Dt (and better -MO=Bytecode\,-S) show something useful:
$ perl5.11.0d -Dt -e'sub foo {return return}; foo' EXECUTING... (-e:0) enter (-e:0) nextstate (-e:1) pushmark (-e:1) gv(main::foo) (-e:1) entersub (-e:1) nextstate (-e:1) pushmark (-e:1) pushmark (-e:1) return (-e:1) leave
$ perl5.11.0d -Dt -e'sub foo {return}; foo' EXECUTING... (-e:0) enter (-e:0) nextstate (-e:1) pushmark (-e:1) gv(main::foo) (-e:1) entersub (-e:1) nextstate (-e:1) pushmark (-e:1) return (-e:1) leave
The disassembler perl -MO=Bytecode\,-S -e'sub foo {return return}; foo' shows the two returns contain op_flags 4 (KIDS) and nothing else.
So I thought ck_return could check if the kid is also a return and warn then. ck_return is called twice\, but it turns out that this op_return has no next and no sibling pointer at this stage. So the new warning is never triggered.
kid->opsibling) mod(kid\, OP_LEAVESUBLV); + } else { + OP *kid; + kid = cLISTOPo->op_first->op_sibling; + if (kid->op_type == OP_RETURN) { + Perl_warner(aTHX\ packWARN(WARN_SYNTAX)\, + "Ignored return return"); + mod(o->op_next\, OP_NULL); + } } return o; }
Breakpoint 1\, Perl_ck_return (my_perl=0x1871fd0\, o=0x18728a8) at opmini.c:7565 7565 PERL_ARGS_ASSERT_CK_RETURN; (gdb) p *o $2 = {op_next = 0x0\, op_sibling = 0x0\, op_ppaddr = 0x5a8f19 \<Perl_pp_return>\, op_madprop = 0x0\, op_targ = 0\, op_type = 190\, op_opt = 0\, op_latefree = 0\, op_latefreed = 0\, op_attached = 0\, op_spare = 0\, op_flags = 4 '\004'\, op_private = 0 '\0'} (gdb) c
So it must be done in peep(). See next mail. -- Reini Urban http://phpwiki.org/ http://murbreak.at/
Rafael Garcia-Suarez schrieb:
2008/6/20 via RT Nicholas Clark \perlbug\-followup@​perl\.org:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful. (Actually\, it seems that anything can be passed the return value of return. C\
works just fine). return is technically parsed as a list operator (LSTOP). That enables using it in compound expressions.
Note that this syntax works also for other control flow statements :
$ perl -wle '$i=3;while(1){print($i--||last)}' 3 2 1
I don't really see a reason to change it.
Well\, if we once want to emit a warning\, here it is:
$ ./perl -e'sub foo {return return}; foo' Ignored return return at -e line 1. $ ./perl -e'sub foo {return 'xx'\, return}; foo' Ignored return return at -e line 1. $ ./perl -e'sub foo {return 1 || return}; foo' $ ./perl -e'sub foo {return 0 || return}; foo' Ignored return return at -e line 1.
I'm not entirely sure if optimizing it away is correct though. The only way I found is in peep()\, not in ck_return() and not in perly.y See http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-06/msg00650.html
Reini Urban http://phpwiki.org/ http://murbreak.at/
On Wed\, June 25\, 2008 1:17 am\, Reini Urban wrote:
David Nicol schrieb:
leaving the question\, why doesn't the optimizer get rid of return?
tentative answer: because the optimizer authors didn't get around to it\, seeing once-per-subroutine as not enough savings to justify the effort.
The optimizer does something with the op_type OP_RETURN. The ck_return() does change all kids to OP_LEAVESUBLV if lvalue'd. The problem is the tokenizer.
Wouldn't this go in a ck_ for leavesub\, leavesublv\, and leavetry? Or maybe lineseq; don't know where all that is used or what its purpose is.
Rafael Garcia-Suarez schrieb:
2008/6/20 via RT Nicholas Clark \perlbug\-followup@​perl\.org:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful. (Actually\, it seems that anything can be passed the return value of return. C\
works just fine). return is technically parsed as a list operator (LSTOP). That enables using it in compound expressions.
Note that this syntax works also for other control flow statements :
$ perl -wle '$i=3;while(1){print($i--||last)}' 3 2 1
I don't really see a reason to change it.
Well\, if we once want to emit a warning\, here it is:
$ ./perl -e'sub foo {return return}; foo' Ignored return return at -e line 1. $ ./perl -e'sub foo {return 'xx'\, return}; foo' Ignored return return at -e line 1. $ ./perl -e'sub foo {return 1 || return}; foo' $ ./perl -e'sub foo {return 0 || return}; foo' Ignored return return at -e line 1.
I'm not entirely sure if optimizing it away is correct though. The only way I found is in peep()\, not in ck_return() and not in perly.y
Reini Urban http://phpwiki.org/ http://murbreak.at/
David Nicol schrieb:
On Mon\, Jun 23\, 2008 at 10:20 AM\, Aristotle Pagaltzis \pagaltzis@​gmx\.de wrote:
And those of us who prefer to use guard clauses and not contort subroutines into nested single expressions cannot avoid `return` at all.
leaving the question\, why doesn't the optimizer get rid of return?
tentative answer: because the optimizer authors didn't get around to it\, seeing once-per-subroutine as not enough savings to justify the effort.
The optimizer does something with the op_type OP_RETURN. The ck_return() does change all kids to OP_LEAVESUBLV if lvalue'd. The problem is the tokenizer.
Concise does not help - identical results. $ perl5.11.0d -MO=Concise\,-exec -e'sub foo {return return}; foo' 1 \<0> enter 2 \<;> nextstate(main 2 -e:1) v:{ 3 \<0> pushmark s 4 \<#> gv[*foo] s 5 \<1> entersub[t2] vKS/TARG\,1 6 \<@> leave[1 ref] vKP/REFC
$ perl5.11.0d -MO=Concise\,-exec -e'sub foo {return}; foo' 1 \<0> enter 2 \<;> nextstate(main 2 -e:1) v:{ 3 \<0> pushmark s 4 \<#> gv[*foo] s 5 \<1> entersub[t2] vKS/TARG\,1 6 \<@> leave[1 ref] vKP/REFC
At least -Dt (and -MO=Bytecode\,-S) show something useful:
$ perl5.11.0d -Dt -e'sub foo {return return}; foo' EXECUTING... (-e:0) enter (-e:0) nextstate (-e:1) pushmark (-e:1) gv(main::foo) (-e:1) entersub (-e:1) nextstate (-e:1) pushmark (-e:1) pushmark (-e:1) return (-e:1) leave
$ perl5.11.0d -Dt -e'sub foo {return}; foo' EXECUTING... (-e:0) enter (-e:0) nextstate (-e:1) pushmark (-e:1) gv(main::foo) (-e:1) entersub (-e:1) nextstate (-e:1) pushmark (-e:1) return (-e:1) leave
The disassembler perl -MO=Bytecode\,-S -e'sub foo {return return}; foo' shows the two returns contain op_flags 4 (KIDS) and nothing else.
So I thought ck_return could check if the kid is also a return and warn then. ck_return is called twice\, but it turns out that this op_return has no next and no sibling pointer at this stage. So the new warning is never triggered.
kid->opsibling) mod(kid\, OP_LEAVESUBLV); + } else { + OP *kid; + kid = cLISTOPo->op_first->op_sibling; + if (kid->op_type == OP_RETURN) { + Perl_warner(aTHX\ packWARN(WARN_SYNTAX)\, + "Ignored return return"); + mod(o->op_next\, OP_NULL); + } } return o; }
Breakpoint 1\, Perl_ck_return (my_perl=0x1871fd0\, o=0x18728a8) at opmini.c:7565 7565 PERL_ARGS_ASSERT_CK_RETURN; (gdb) p *o $2 = {op_next = 0x0\, op_sibling = 0x0\, op_ppaddr = 0x5a8f19 \<Perl_pp_return>\, op_madprop = 0x0\, op_targ = 0\, op_type = 190\, op_opt = 0\, op_latefree = 0\, op_latefreed = 0\, op_attached = 0\, op_spare = 0\, op_flags = 4 '\004'\, op_private = 0 '\0'} (gdb) c
So it must be done in peep(). -- Reini Urban http://phpwiki.org/ http://murbreak.at/
On Fri\, Jun 20\, 2008 at 08:04:27AM -0700\, Nicholas Clark wrote:
$ ./perl -Ilib -e 'sub foo {return return}' $
How come this isn't a syntax error? It can't possibly do anything useful. (Actually\, it seems that anything can be passed the return value of return. C\
works just fine).
Well\, some people think that always using a 'return' makes code easier to understand. Clearly\, 'return return' makes it even easier.
Abigail
@cpansprout - Status changed from 'open' to 'rejected'
Migrated from rt.perl.org#56150 (status was 'rejected')
Searchable as RT56150$