Re: PHP True Async RFC - Stage 2

From: Date: Mon, 17 Mar 2025 07:58:22 +0000
Subject: Re: PHP True Async RFC - Stage 2
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-126800@lists.php.net to get a copy of this message
Hello. In this email, I will focus only on the syntax because it is a separate and rather complex topic. First, the RFC does not clearly describe the syntax, which needs to be fixed. Second, you are right that methods and operators cause confusion. However, I really liked the $scope->spawn() construct in the example code, as it feels the most natural compared to spawn in. Moreover, the spawn in expression is quite complex to implement, but I don't have enough experience to evaluate it properly. ## Defer I have nothing against the suspend keyword. However, the defer keyword raises some questions. "Defer" means to postpone something (to delay execution). But in this case, it’s not about "postponing" but rather "executing upon function block exit." I don't know why the creators of Go chose this word. I considered finally, but it is already used in the try block. The implementation also concerns me a bit. It seems that to fully implement the defer block, we would need something similar to finally, or essentially make defer create an implicit try...finally block. ## Spawn Operator Yes, the chosen syntax has some ambiguity because there are two versions. However, I didn't like the other options, mainly due to their verbosity. **General syntax:** ```php spawn [in <scope>] function [use(<parameters>)][: <returnType>] { <codeBlock> }; ``` where: - parameters - a list of parameters passed to the closure. - returnType - the return type of the closure. - codeBlock - the body of the closure. Examples: ```php spawn function { echo "Hello"; }; spawn function:string|bool { return file_get_contents('file.txt'); }; // Incorrect syntax spawn { echo "Test\n"; }; ``` ##### In scope expression The in keyword allows specifying the scope in which the coroutine. ```php $scope = new Async\Scope(); $coroutine = spawn in $scope function:string { return "Hello, World!"; }; function test(): string { return "Hello, World!"; } spawn in $scope test(); ``` The scope expression can be: - A variable ```php spawn in $scope function:void { echo "Hello, World!"; }; ``` - The result of a method or function call ```php spawn in $this->scope $this->method(); spawn in $this->getScope() $this->method(); ``` The form spawn <callable>(<parameters>); is a shorthand for spawn use(<callable>, <parameters>) { return ... }; The expression <callable>(<parameters>); is not executed directly at the point where spawn is used but in a different context. There is a slight logical ambiguity in this form, but it does not seem to cause any issues with comprehension. As for the form: spawn (<expression>)(parameters) — I suggest not implementing it at all. It makes the code unreadable, and carries no meaningful advantage. Saving a single variable only to get lost in parentheses? It's not worth it.. :) ### Spawn Form The form spawn <callable>(<parameters>); is a shorthand for: ```php spawn use(<callable>, <parameters>) { return ... }; ``` The expression <callable>(<parameters>); is not executed directly at the point where spawn is used but in a different context. There is a slight logical ambiguity in this form, but it does not seem to cause any issues with comprehension. As for the form: ```php spawn (<expression>)(parameters); ``` I suggest not implementing it at all. It is simply terrible, makes the code unreadable, and carries no meaningful advantage. Saving a single variable only to get lost in parentheses? It's not worth it.. :) ### Why do I use the function keyword in the second form? Only to allow defining the return type. In principle, both forms are equivalent: ```php spawn {}; spawn function {}; ``` I also like the function keyword because it unambiguously indicates that this is not just a block of code but specifically a closure. What I don’t like: This form might complicate semantic analysis since now there are two types of closures to parse. Intuitively, it would be good to define it like this: ```php spawn function() use() {}; ``` — meaning to literally mirror the standard closure definition. This way, an existing analysis block could be reused. But what should we do with parameters? :) In other words, I would prefer this aspect to be reviewed by someone who is equally well-versed in the implementation. --- Ed.

« previous php.internals (#126800) next »