Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126834 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id ACC9A1A00BC for ; Wed, 19 Mar 2025 07:07:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1742367918; bh=8SScDw5UPGdOInKxB0epmlvExrEMn0f2oGDHaGf/fxo=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=DUGJYo5JwOSbI4ZQ53K3eE5CmHtHMHVDFeRI4dcvp1FDoBPbgsRZzLX34afNixVfY u2btu4or+Qw5w/7/yJP37bPHD0r6WI2Zi41dMjTNPhk853IdOSA5MTGHX3uLT+w7e/ aBTMU1cA4zSqW6BTci7fSlJOcNo5zZAyOeShR60u/dRfHBcYjQs8utn1/wfnAgtVrp Wia478wcYF/QkdioMyJmizPiN0/aWIitCLfLCBBUV65+1C8Ka4LTMjoWOI1RzsJ7eA NOWVpn90KqHCKhL2vWf57YgL5okHvZJihgBB5A+/pEdevc6GNCnfeSxfa+KtwhCf/5 vun4300su6Jjg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 54FEE18004E for ; Wed, 19 Mar 2025 07:05:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_40,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 19 Mar 2025 07:05:17 +0000 (UTC) Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-6f74b78df93so66077627b3.0 for ; Wed, 19 Mar 2025 00:07:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742368067; x=1742972867; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=8SScDw5UPGdOInKxB0epmlvExrEMn0f2oGDHaGf/fxo=; b=InC5MZCxpHvEWEZMnL9jGQ+r/qjYkk7CJ5UWTnS38uCOuuSP3+Szv99PtiVEx0CXlh fHZtyWACAuuMqaufrjn11+mVgmFs+z3L/MZn64aM+OIsu3OmwnfGZwYN2Tc65lfib+hr cAiLVkh/co9sGzQcpuV3fa3nyi0cOuNdgf3LfP8mfBtIF2sx9ety7h2iaJ584iQ6FzKX t6a+AhRk1vQ0ItgYBoUKreFXYQAGQEd5EFnsQcPjU5IjjjvVab7oF56jJRlRqXtCUl+K huotcykHNE6QbrT+8R3s5DnARKmNsS39WNgU6sWXAB8rZNCatFmyytYZMZIlkD0dkbwu 2ELA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742368067; x=1742972867; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=8SScDw5UPGdOInKxB0epmlvExrEMn0f2oGDHaGf/fxo=; b=Sxe4Fm+4BafjWs6fBtR5Qf2aGNdU5KmhNmSnoo/xGy3kqjr5jXFPOR26b6/reW1ht4 dbSfG9AqYGBTwGNfxkhvLC4glAY70e+uQ72WVOBbp/oEUz2QY+KQrj3Ag0B2lUCeOQAE F06b5U9Kvuw1h5z9RYKx/pyH/K8fiFGKWYBoJzqj7ddAMsco7awPGGzVVKUp8vLgzHyP KxRri3KiEN5ae6yizQxOnIe+KchvMBSAduAmn3Pbcw4SF4tXh8I6+n+c2xvCfbC7aJQB SqpjiupoNbeQHKt01FeQWPaBDwtZsK50mcA/iJ2ujOGAZh1gv97SIqTQHFi92ihpX0hm 8cdg== X-Gm-Message-State: AOJu0Yz9aZeXsWGheKuQMBZv48UEmnAj1mow8TiBfrAlNi+DI/qbiMPM DvFb/i36kUgtT2ecoRlLl2Ol683NrSQb+QZPrNsG0MLZeeA5VBnTqvYbJWmE09eenpfx+Q2rVv5 oGqnYlut3lMfZtXU9NeDcfjoqFKlW2yzV8FE= X-Gm-Gg: ASbGncsX/x3JTcaB5mwBTZl2F5jEXGDGwP//Ukrnx52PlydC9YtmDhEXoiA8bEMzQZm PD/NICzXjoN/9EcmPM6O6aQTGOq/2TyQQ9bQ4ZWvt52dPCqbxUngiLaovfj42DZ+KN+vaNKjQjr H2TBueT7eykDv0l4I5+NXyc8qLqA== X-Google-Smtp-Source: AGHT+IFg0/aopHD9GgBDLQ4U0UnFcVnAVAgk8Ly8CgcembVPeO+0O0PpLEfUBvrnLSBtsA6FyFwGS5pj2jjnNPhpBLE= X-Received: by 2002:a05:690c:4b81:b0:6f9:9891:7a7f with SMTP id 00721157ae682-7009c02dea4mr19268017b3.25.1742368067411; Wed, 19 Mar 2025 00:07:47 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <72bd5401-53a9-409f-ad45-687333401961@rwec.co.uk> In-Reply-To: Date: Wed, 19 Mar 2025 09:07:36 +0200 X-Gm-Features: AQ5f1JrCHxzRKATUMDOzG5qtszavj1U3nGXRqaP9WGyH9igZSMUaLt1ysKAVBMQ Message-ID: Subject: Re: [PHP-DEV] PHP True Async RFC - Stage 2 To: "Rowan Tommins [IMSoP]" Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000b9f0c70630acad2f" From: edmond.ht@gmail.com (Edmond Dantes) --000000000000b9f0c70630acad2f Content-Type: text/plain; charset="UTF-8" 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 `, 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 ] [()]; ``` **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. --000000000000b9f0c70630acad2f Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Continuing the discussion from [[PHP-DEV] PHP True Async R= FC - Stage 2](https://discourse.thephp.foundation/t/php-d= ev-php-true-async-rfc-stage-2/1573/24):

[quote=3D"Rowan_Tom= mins_IMSoP, post:24, topic:1573"]
I'm still confused why you st= arted talking about how to implement "defer". Are you saying that= "onExit" and "defer" are different things? Or that giv= ing it dedicated syntax changes the implementation in some fundamental way?=
[/quote]

I meant that the `defer` operator is needed in the lang= uage not only in the context of coroutines but in functions in general. In = essence, `defer` is a shortened version of `try-finally`, which generates m= ore readable code. =C2=A0

Since that's the case, I shouldn't= describe this operator in this RFC. However, `onExit()` and `defer` are es= sentially almost the same. =C2=A0

[quote=3D"Rowan_Tommins_IMSoP= , post:24, topic:1573"]
As with any other callable, it would be cal= led with no arguments. It was just an illustration, because the function_na= me(...) syntax is one of many ways of creating a callable in PHP.
[/quot= e]

I think I understand your point. =C2=A0
`spawn <callable>= ;`, where `callable` is literally any expression that is considered callabl= e. =C2=A0
OK. Let's transform that to rules:

The general synt= ax of the `spawn` operator:

```php
spawn [with <scope>] <= ;callable>[(<parameters>)];
```

**where:**

- **ca= llable** a valid expression whose result can be invoked.

Examples:
```php
spawn "function_name";

// With variable$callable =3D fn() =3D> sleep(5);
spawn $callable;

// With ar= ray expression
spawn ([$this, "method"]);
// With condition=
spawn ($condition ? $fun1 : $fun2);
// As function result
spawn (= getClosure());

// Closures:
spawn (function() use(): string { ret= urn "string"; });
spawn (fn() =3D> sleep(5));
// with cl= osure expression
spawn (sleep(...))(5);

// Simplified forms
sp= awn sleep(5);
spawn function() use(): string { return "string"= ; };
```

- **parameters** a list of parameters that will be passe= d to the callable expression.
- **scope** an expression that should reso= lve to an object of class `Async\Scope`.

Examples:

```php
= spawn with $scope file_get_contents("http= ://localhost");
spawn with $this->scope file_get_contents(&q= uot;http://localhost");
spawn with= $this->getScope() file_get_contents("= http://localhost");
spawn with getScope() file_get_contents(&qu= ot;http://localhost");
spawn with = ($flag ? $scope1 : $scope2) file_get_contents("http://localhost");
```

As you may have noticed, t= here is still a special form to avoid using `"()"`. However, over= all, this syntax looks quite cohesive. Did I get the idea right?

[qu= ote=3D"Rowan_Tommins_IMSoP, post:24, topic:1573"]
The only cav= eat is that calls using the nullsafe ?-> operator are forbidden - for re= asons directly related to the feature, not because Nikita thought they were= ugly.
[/quote]

Yes, that's exactly what we'd like to avo= id.

[quote=3D"Rowan_Tommins_IMSoP, post:24, topic:1573"]But most likely you'd still want a separate syntax for a direct funct= ion call, however you want to spell it:
[/quote]

**Exactly!** It = turns out that the expression `spawn something();` =C2=A0
can be interpr= eted as if `something` is a PHP constant rather than a function. =C2=A0
=
This creates an ambiguous situation in the language: =C2=A0
```phpconst MY_CONST =3D "somefunction";
spawn MY_CONST(); // What= happens here??? :)
```

With your help, we seem to have identifie= d all the pitfalls. Now we can put them together and come up with the best = solution.
--000000000000b9f0c70630acad2f--