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.
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*/
};
?>
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
function get_nationality_string(int $country_code) : string | "unknown"
{
return;
};
If I understand you correctly, your idea is that the "return;" here would be treated automatically as "return 'unknown';" I think that's an interesting idea, although I can't immediately think of a situation where I'd use it.
My main concerns are with the syntax:
- Firstly, specific literals aren't currently allowed in return types, and allowing them would have other implications. Three exception is "false", which is allowed because of its common use as an error code, including in many internal functions.
- Secondly, it could be ambiguous which is intended to be the default value, if the return type was something like int|"yes"|"no"
Perhaps the default return value would need to be specified separately from the return type somehow?
Regards,
Hi Hamza,
Welcome to the list, and thanks for sharing this idea.
--
Rowan Tommins
[IMSoP]
Hi Rowan,
Thanks for the response. Luckily, you razed the question that I thought about after posting the first request.
My idea develops on respecting both return type hints and union types. The current implementation of empty return does not respect the function signature. As I have mentioned in the first message that empty return returns null regardless of the return type set, I propose that an empty return may return the defaults of types i.e. an empty string if the type is string, an empty array if the type is array, zero if the type is int etcetera. I have also noted that in a void typed function, an empty return may return nothing and just end the execution.
The current implementation of empty return is only favourable for mixed type. In other words, when the return type is mixed, an empty return may return null. Otherwise, it should respect the declared return type.
After the release of union types, there emerges a question regarding the selection of default return value. To solve this problem, the type on the very right side will be used.
Now, I come to your question, Rowan. As of today, only false and null literals are supported. If both assist in error handling, why does empty return always returns null?
I tested this code on shell.
var_dump($a=(function():string|false{return;})());
It produced:
Fatal error: A function with return type must return a value in php shell code on line 1.
Here comes the inconsistency. To resolve the problem, I suggest to respect the literals first. If literals are not found, respect the first type on the right side.
Moreover, only two standalone literals, false and null, will be supported. Otherwise, the literal should be one of the types specified. If multiple literals are specified, it will throw an error of multiple literals. The literal can be a simple literal, such as, "unknown" 0, and a constant expression, like self :: MSG_UNKNOWN. It will help maintain the multi-language scripts.
I hope I have been able to make my stance clear.
Best
Hamza Ahmad
-----Original Message-----
From: Rowan Tommins rowan.collins@gmail.com
Sent: Thursday, March 11, 2021 1:45 PM
To: internals@lists.php.net
Subject: Re: [PHP-DEV] Honour the Default Value of 'return' Statement According to the Function Signature
<?php
function get_nationality_string(int $country_code) : string | "unknown"
{
return;
};
If I understand you correctly, your idea is that the "return;" here would be treated automatically as "return 'unknown';" I think that's an interesting idea, although I can't immediately think of a situation where I'd use it.
My main concerns are with the syntax:
- Firstly, specific literals aren't currently allowed in return types, and allowing them would have other implications. Three exception is "false", which is allowed because of its common use as an error code, including in many internal functions.
- Secondly, it could be ambiguous which is intended to be the default value, if the return type was something like int|"yes"|"no"
Perhaps the default return value would need to be specified separately from the return type somehow?
Regards,
Hi Hamza,
Welcome to the list, and thanks for sharing this idea.
--
Rowan Tommins
[IMSoP]
--
To unsubscribe, visit: https://www.php.net/unsub.php
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--
To unsubscribe, visit: https://www.php.net/unsub.php
Thank you for providing me with the feedback, experts! Initially, I wanted empty returns in void functions. When I prepared the request, I included the other solutions that I felt important and worth adding. Is it not possible to go with empty returns in void functions? I agree that the code can be adjusted to fit the current environment; still, people avoid writing lengthy blocks of code. An empty return with defaults will help them with the code that is easier to maintain.
I clarified my stance on first email in a response to a respectable member of the list. I do not know why that email is not appearing on externals. I will make sure that next time I post an external URL that contains the changelog and do not clutter the mailing list.
I am again thankful to you all!
Best
Hamza Ahmad
-----Original Message-----
From: Mike Schinkel mike@newclarity.net
Sent: Thursday, March 11, 2021 10:05 PM
To: office.hamzaahmad@gmail.com
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] Honour the Default Value of 'return' Statement According to the Function Signature
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--
To unsubscribe,
visit: https://www.php.net/unsub.php