> On Mar 10, 2021, at 10:37 PM, office.hamzaah...@gmail.com wrote:
> 
> Hello Internals,
> I congratulate you for the successful release of PHP 8.0.3. I also
> appreciate your efforts to bring union types and return type hints.
> Although the type hints have made debugging more easier, it has created
> another problem for those that use 'return' to end the execution of a
> function or method call.

Welcome.

> There are mainly two usages of 'return'. First ends the execution of the
> remaining statements. Second returns a value. The return type hints aids
> with the second usage and ignores the former facility. In other words, if
> one wants to avoid large code blocks i.e. the conditional blocks, it can
> write like following.
> 
> <?php
> function foo()
> {
>       If (true /*condition1*/)
>               return;
> 
>       if (!false /*condition2*/)
>               return;
> 
>       /*the remaining part of a function*/
> };
> ?>

However, I agree with Larry.  This feels either like a code smell and/or could 
be handled with a variable.

This pattern can be very frustrating in other people's code when I either need 
to debug it or might want to debug it to learn the code because it requires 
setting IDE breakpoints in many places to be sure that catch an exit. And 
invariably I miss breakpointing a return when debugging and am left wondering 
what happened.  See https://youtrack.jetbrains.com/issue/WI-40862

As an alternate I developed a technique using `do{...} while(...)` in a novel 
way that I wish PHP supported more cleanly, but it nonetheless works great. 

The technique uses `do {...} while(false)` to create a block that break can 
exit early on guard clauses, for example (btw, I would return `null` instead of 
`'unknown'` and enclose the breaks in braces for the `if(...)` statement, but I 
wanted my example to be equivalent to yours):

<?php
function foo() {

    $value = 'unknown';           // Set the default return value up here
    
    do {

        if (/*condition1*/)    
                break;                  // <== see, no need for a value here

        if (/*condition2*/)
                break;                  // <== or here!
        
        /*the remaining part of a function that sets $value */

    } while (false);
    
    return $value;                      // The only return in this function. 
Debugging nirvana.

}

Maybe you can use this approach instead to allow you to not have to annotate 
each early exit with a return value?

-Mike

P.S. Ideally PHP would support (something like) a naked `do{...}` — or a naked 
`try{...}` that supports `break` — though I have not tried to convince the list 
because status quo has the inertia here. But I mention this in hopes others see 
value in it and would help champion the idea. #fwiw


> The above function returns null if conditions are met. Otherwise, it returns
> no value. It was okay when there was no concept of return type hints. When
> return types have been introduced, the behaviour needs to be evolved, too.
> What if the return type was set 'int|float' in the above example? The
> compiler would give following error:
> Fatal error: A function with return type must return a value.... Similarly,
> a function with ': void' signature produceed that a function may not return
> a value.
> To resolve such a problem, I request to honour the function signature when
> you evaluate return statements. Instead of looking for no 'return'
> statements in ': void' functions, verify whether a function specifies a
> return value. If the function returns a type other than the types declared
> in the signature, it may produce wrong type error. If a function with void
> returns a value i.e. contains a non-empty return (return;) statement, the
> compiler may throw an error stating that a function with void signature must
> not return a value.
> Likewise, 'return' may return an empty array if the return type was set to
> array; the similar case applies to string, int, float, object etcetera. In
> the case of ': void' signature, 'return' only ends the execution and returns
> no value.
> PHP also allows to specify only returning 'false' from a function call. What
> if you extend this functionality and allow specifying literals including
> null? If nulls are also allowed, the backword behaviour could be
> impleamented. For example:
> public function foo() : string| null;
> 
> Consider the following example for literals.
> <?php
> function get_nationality_string(int $country_code) : string | "unknown"
> {
>       return;
> };
> ?>
> 
> I am positive that you will consider my request and provide me with the
> feedback in case of any inconsistency in my argument. I wish you best of
> luck for the on-going work for the PHP 8.1.
> Best Regards
> Hamza Ahmad
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to