>
> 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.

Reply via email to