On 19/03/2025 19:24, Edmond Dantes wrote:
> Yes, that would probably be a bad choice as well. Which is why I've repeatedly suggested a different keyword, and AFAIK you still haven't actually voiced an opinion on that.


Does this concern the syntax of `spawn block {}` or did I miss something?


We're talking around in circles a lot here, I think, let's try to reset and list out a load of different options, as abstractly as possible.

I'm going to use the word "keyword" in place of "spawn", just to separate *syntax* from *naming*; and where possible, I'm going to use the names from the current grammar, not any other placeholders.


1: keyword expr
2: keyword function_call
3: keyword expr_except_function_call
4: keyword inline_function
5: keyword_foo expr
6: keyword_bar function_call
7: keyword '{' inner_statement_list '}'


#1 is the most flexible: you have some way of specifying a callable value, which you pass to the engine, maybe with some arguments (concrete example: "spawn $my_closure;")

#2 is the most concise for the common case of using an existing function, because you don't need to make a callable / closure pointing to the function first (concrete example: "spawn my_function('my argument');")

BUT these two rules conflict: any function_call is also an expr, so we can't say "if it's an expr, do this; if it's a function_call, do that", because both are true at once.


The next four are compromises to work around that conflict:

#3 is a version of #1 which doesn't conflict with #2 - introduce a new grammar rule which has all the things in expr, but not function_call. This is technically fine, but maybe confusing to the user, because "spawn $foo == spawn $foo()", but "spawn foo() != spawn foo()()", and "spawn $obj->foo != $obj->foo()".

#4 is really the same principle, but restricted even further - the only expression allowed is the declaration of an inline function. This is less confusing, but has one surprising effect: if you refactor the inline function to be a variable, you have to replace it with "$foo()" not just "$foo", so that you hit rule #2

#5 and #6 are the "different keywords" options: they don't conflict with each other, and #1 could be used with #6, or #2 with #5. In concrete terms, you can have "spawn_func_call $foo() == spawn_closure $foo", or "spawn $foo() == spawn_closure $foo", or "spawn_func_call $foo() == spawn $foo".


#7 is the odd one out: it hides the closure from the user completely. It could be combined with any of the others, but most likely with #2



In PHP, code blocks are not all the same.
- `if` / `then` / `else` / `try` / `switch` **do not create a new scope**.
- `function` **does create a new scope**.

When a programmer writes:
```php
$x = 5;
spawn {$x++};
```
Will they easily understand that |$x++| is not modifying the same |$x| as before? No, they won’t. They will have to remember that |spawn {}| creates a closure, just like |function| creates a closure with a separate scope.


OK, thanks; I think this is the point that I was missing - I was thinking that the engine creating a closure was just an implementation detail, which could be made invisible to the user. But you're right, the way variable scope works would be completely unlike anything else in the language. That probably rules out #7

But I do want to come back to the question I asked in my last e-mail: what is the use case we're trying to cater for?

If the aim is "a concise way to wrap a few statements", we've already failed if the user's writing out "function" and a "use" clause.

If the aim is "a readable way to use a closure", rule #2 is fine.

Yes, it means some extra parentheses if you squeeze it all into one statement, but it's probably more readable to assign the closure to a temporary variable anyway:

// Legal under rule #2, but ugly
spawn (function() use($whatever) {
    do_something($whatever);
})();

// Requires rule #4, saves a few brackets
spawn function() use($whatever) {
    do_something($whatever);
};

// Only needs rule #2, and perfectly readable
$foo = function() use($whatever) {
    do_something($whatever);
}
spawn $foo();


--
Rowan Tommins
[IMSoP]

Reply via email to