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.

Reply via email to