develooper 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


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About