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