Nested functions
| From: | Luis - SoftSAT Sistemas | Date: | Thu, 13 Aug 2020 14:35:33 +0000 |
| Subject: | Nested functions | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-111506@lists.php.net to get a copy of this message | ||
13.08.2020, 10:52, "Claude Pache" <claude.pache@gmail.com>:
>> Le 12 août 2020 à 22:05, Luis - SoftSAT Sistemas <luis@softsatsistemas.com.br> a
>> écrit :
>>
>>>> Le 12 août 2020 à 20:19, Luis - SoftSAT Sistemas
>>>> <luis@softsatsistemas.com.br> a écrit :
>>>>
>>>> In the effort to make PHP a better language i want to ask why not "fix"
>>>> nested functions as suggested in (https://wiki.php.net/rfc/true-nested-function-support) or block
>>>> their usage?
>>>> The current behavior is a lot unexpected.
>>>>
>>>> I am new here, sorry if it was already discussed, i can't find a good way to
>>>> search the mailing history.
>>>
>>> Hi,
>>>
>>> Defining a global function inside another function is not useless. Here is a dummy
>>> example:
>>>
>>> ```php
>>> // a.php
>>> spl_autoload_register(function ($classname) {
>>> if ($classname === 'Foo\\B')
>>> require 'foo/b.php';
>>> })
>>>
>>> // foo/b.php
>>> namespace Foo;
>>>
>>> class B {
>>> // ...
>>> }
>>>
>>> function some_helper(....$args) {
>>> // ...
>>> }
>>> ```
>>>
>>> The global function
Foo\some_helper is defined inside
>>> the function used as autoloader.
>>>
>>> Also, from the RFC:
>>>
>>>> They exist in the global namespace.
>>>
>>> I think you meant “They exist in the global scope”? because they are defined in the
>>> namespace corresponding to the eventual namespace declaration of the
>>> file.
>>>
>>> —Claude
>>
>> You are right Claude, i wasn't thinking about this use case.
>>
>> But outside of this use case more problems arise.
>> If foo/b.php have some global variable and some function
>> that use it the function breaks because the global variable will be "included" into
>> current scope, while the functions into namespace scope.
>> ```php
>> //a.php
>> function foo() {
>> require 'b.php';
>> //var_dump($something);
>> }
>>
>> foo();
>>
>> var_dump(bar());
>>
>> //b.php
>> $something = 10;
>>
>> function bar() {
>> global $something;
>> return $something;
>> }
>> ```
>> I expected the var_dump(bar()); output to be
>> int (10), but it was NULL, while if
>> i do var_dump($something); from
>> foo() it outputs int(10) as
>> "normally expected".
>> Given that "bar()" are at namespace scope, this can be "fixed" changing
>> $something = 10; to $GLOBALS['something']
>> = 10;, but that doesn't change the fact that this behavior are odd and not
>> intuitive.
>>
>> PS: I known that global variables are a bad thing, it was just an example.
>>
>> Anyway now i see that changing this will break the auto loader system.
>>
>> About the RFC you are right, they are wrong about the scope, but the RFC aren't mine,
>> i just found it while searching about the subject.
>>
>> --L. Henrique
> About global variables; it is an issue I encountered once upon a time when refactoring code.
> The short term solution is to declare the global variables both in the inner and the outer scope:
>
> ```php
> // b.php
> global $something;
>
> $something = 10;
>
> function bar() {
> global $something;
> return $something;
> }
> ```
>
> Functions in PHP have the following characteristics: they are defined globally, and they
> don’t inherit variables from their parent scope. On the other hand, anonymous functions (closures)
> are available locally, and they may import variables from their parent scope. Both sort of functions
> have their usages.
>
> About the RFC page: It looks to me like an old abandoned stub. It isn’t even listed
> on https://wiki.php.net/rfc
>
> —Claude
I think it's all clear now, thanks Claude!
-- L. Henrique