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.