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.

Reply via email to