Front page | perl.perl5.porters |
Postings from June 2008
Re: [perl #56150] return return
Thread Previous
|
Thread Next
From:
Mark Mielke
Date:
June 23, 2008 06:52
Subject:
Re: [perl #56150] return return
Message ID:
485FAA80.7060508@mark.mielke.cc
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>
Thread Previous
|
Thread Next