Continuing the discussion from [[PHP-DEV] PHP True Async RFC - Stage 2]( https://discourse.thephp.foundation/t/php-dev-php-true-async-rfc-stage-2/1573/24 ):
[quote="Rowan_Tommins_IMSoP, post:24, topic:1573"] I'm still confused why you started talking about how to implement "defer". Are you saying that "onExit" and "defer" are different things? Or that giving it dedicated syntax changes the implementation in some fundamental way? [/quote] I meant that the `defer` operator is needed in the language not only in the context of coroutines but in functions in general. In essence, `defer` is a shortened version of `try-finally`, which generates more readable code. Since that's the case, I shouldn't describe this operator in this RFC. However, `onExit()` and `defer` are essentially almost the same. [quote="Rowan_Tommins_IMSoP, post:24, topic:1573"] As with any other callable, it would be called with no arguments. It was just an illustration, because the function_name(...) syntax is one of many ways of creating a callable in PHP. [/quote] I think I understand your point. `spawn <callable>`, where `callable` is literally any expression that is considered callable. OK. Let's transform that to rules: The general syntax of the `spawn` operator: ```php spawn [with <scope>] <callable>[(<parameters>)]; ``` **where:** - **callable** a valid expression whose result can be invoked. Examples: ```php spawn "function_name"; // With variable $callable = fn() => sleep(5); spawn $callable; // With array expression spawn ([$this, "method"]); // With condition spawn ($condition ? $fun1 : $fun2); // As function result spawn (getClosure()); // Closures: spawn (function() use(): string { return "string"; }); spawn (fn() => sleep(5)); // with closure expression spawn (sleep(...))(5); // Simplified forms spawn sleep(5); spawn function() use(): string { return "string"; }; ``` - **parameters** a list of parameters that will be passed to the callable expression. - **scope** an expression that should resolve to an object of class `Async\Scope`. Examples: ```php spawn with $scope file_get_contents("http://localhost"); spawn with $this->scope file_get_contents("http://localhost"); spawn with $this->getScope() file_get_contents("http://localhost"); spawn with getScope() file_get_contents("http://localhost"); spawn with ($flag ? $scope1 : $scope2) file_get_contents("http://localhost "); ``` As you may have noticed, there is still a special form to avoid using `"()"`. However, overall, this syntax looks quite cohesive. Did I get the idea right? [quote="Rowan_Tommins_IMSoP, post:24, topic:1573"] The only caveat is that calls using the nullsafe ?-> operator are forbidden - for reasons directly related to the feature, not because Nikita thought they were ugly. [/quote] Yes, that's exactly what we'd like to avoid. [quote="Rowan_Tommins_IMSoP, post:24, topic:1573"] But most likely you'd still want a separate syntax for a direct function call, however you want to spell it: [/quote] **Exactly!** It turns out that the expression `spawn something();` can be interpreted as if `something` is a PHP constant rather than a function. This creates an ambiguous situation in the language: ```php const MY_CONST = "somefunction"; spawn MY_CONST(); // What happens here??? :) ``` With your help, we seem to have identified all the pitfalls. Now we can put them together and come up with the best solution.