>
> You're cheating again - you've put an extra pair of brackets around one
> expression and not the other, and assumed they'll work differently, but
that's
> not the grammar you proposed.
>
Why am I cheating?
> spawn (getClosure());
This is an honest statement, provided that the second parentheses are
optional. The full notation would be:
> spawn (getClosure())();
> Instead you'd have to write this:
> spawn (function() use(): string { return "string"; });
Exactly right, that's how it should be according to PHP syntax.
Therefore, if we want to get rid of double parentheses, we need a separate
rule for closures.
I would name these two cases as follows:
* spawn callable – the general usage case
* spawn closure – the special case for closures
I don't think these two rules make the language inconsistent because the
`function` keyword allows separating the first expression from the second
one.
`spawn function` means that a `Closure` definition follows.
Accordingly, there should be no additional parentheses `()` at the end.
The reverse meaning is that if `spawn` is not followed by the `function`
keyword, then it must be a valid expression that can be enclosed in
parentheses.
There are some doubts about whether all situations are correct, but so far,
this is how it works for me:
- call a standard PHP function
```php
spawn file_get_contents('file1.txt');
```
- call a user-defined function
```php
function example(string $name): void {
echo "Hello, $name!";
}
spawn example('World');
```
- call a static method
```php
spawn Mailer::send($message);
```
- call a method of an object
```php
$object = new Mailer();
spawn $object->send($message);
```
- self, static or parent keyword:
```php
spawn self::send($message);
spawn static::send($message);
spawn parent::send($message);
```
- call `$class` method
```php
$className = 'Mailer';
spawn $className::send($message);
```
- expression
```php
// Use result of foo()
spawn (foo())();
// Use foo as a closure
spawn (foo(...))();
// Use ternary operator
spawn ($option ? foo() : bar())();
```
- call array dereference
```php
$array = [fn() => sleep(1)];
spawn $array[0]();
```
- new dereference
```php
class Test {
public function wait(): void {
sleep(1);
}
}
spawn new Test->wait();
```
- call dereferenceable scalar:
```php
spawn "sleep"(5);
```
- call short closure
```php
spawn (fn() => sleep(1))();
```
> Sorry, what is exactly what we'd like to avoid?
Syntax ambiguities.
But it seems that avoiding them completely is impossible anyway because
I've already found an old case where a property and a method are used in
the same expression.