Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126852 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 1A0601A00BC for ; Thu, 20 Mar 2025 04:57:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1742446491; bh=K5nYnKekjtr23yXp2ijEtLpP2q987yC9sawn6sZzv1k=; h=Date:From:To:In-Reply-To:References:Subject:From; b=LhbQ+okTeZQZ5hG6MRO9HerOxlOoBzSDh8nBjpzdDfyKgiOD5qsO0Af7PVkbIWotx 07Net4c5lr2J9d42UH79ufhFXXRoH+tFWYDZG2Tl/2oQ69dN33MbbEjAD2494qaYpB uciB8kpUWLrPyrJsxVJSpreOAciv4HnmvZylg2g9TnpvgycUS3QavtKswNEQUjkZgd JrMIbrrN0p7RG9PZTgPVkllETmDMWCG0cEw7TbOlbMbhYnvSG1Ej9aj3BHia4jCUVp kSeWic/G9s6RPho9qyCg0LV7CugqHKJMOkyBGEAmwd3n8aJWJYxxw2mmwJLeB2zlD3 FhVye3Z8WDAjA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id F1C2D180081 for ; Thu, 20 Mar 2025 04:54:49 +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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-b2-smtp.messagingengine.com (fhigh-b2-smtp.messagingengine.com [202.12.124.153]) (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 ; Thu, 20 Mar 2025 04:54:49 +0000 (UTC) Received: from phl-compute-04.internal (phl-compute-04.phl.internal [10.202.2.44]) by mailfhigh.stl.internal (Postfix) with ESMTP id 29E9F25401E9 for ; Thu, 20 Mar 2025 00:57:20 -0400 (EDT) Received: from phl-imap-06 ([10.202.2.83]) by phl-compute-04.internal (MEProxy); Thu, 20 Mar 2025 00:57:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to; s=fm1; t=1742446640; x=1742533040; bh=6alGnIu5tJfLqn+QUspqK 5CF1jyMkxr4tZ5dxMzUczs=; b=x7lfCGu7BTy42dibWhdDgjeIbVZo95xoE8/Bx vtzXyOLPeZkyXDGMdHMmsf2UWFtY5EOs2CAWo5PfVUMRG5XeW4jm1GHwxqcX7TJq 5r8NunQCHj8o8qB6cXm7h6L1IuAiewb5porOcMXxFnqWN6czqG+Sdvu2hAerLERi bE1ebRXsTwDre/yoGt78zdHBTO2Gh9r94dx00pGrsKH/xVa36W1bLMGLotR+ac2b H26gaSjeEpfHavDAeCK+PIC/a4rVKYJ6YYg8VB2+NK2jxZwgOXW2z5GqQgu+fBQ/ 05MNPKt0GML8gsdQuJWTgq1B9Zg2Aj9dNUqPDtFSyBzsZyv/Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1742446640; x=1742533040; bh=6 alGnIu5tJfLqn+QUspqK5CF1jyMkxr4tZ5dxMzUczs=; b=zigaS1q1DzDt5Chpp w1PN8hnIY3iSp+dxQBEiOUgYmRJbGEUkSs1xtWPbxNYgCspyd1TyVl1JpKbXABKX /9DgWY0HAJLTlszjkAUIckf/mpBFMwgB4STFpMlvWbxWTbIFPB2+8q2G4bae2e4y jqRDuhe6lSoqagewMaAU5VZ2idU/YEC5Y6nqi1C4PFVAs9l/4UrYdR/m+hPnXalT db3SAzjTWaB5ICYdceYQYZ4TuTsDKPFkgkF/Hgx9Fx/hl+VWAta4RbtsndjXdU7N wUkMZJP7Qfokeg1u3akYXctGPqvIsZ6rse8ltDYgEAvpTbClHdAj4j3hpeXxI0+L IVReA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddugeejfedtucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvffkjghfufgtgfesthhqredtredt jeenucfhrhhomhepfdfnrghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrh hfihgvlhguthgvtghhrdgtohhmqeenucggtffrrghtthgvrhhnpeffieeivdfhvdeguddt tdegteeiueegvefhteehfeeffeetudeitdehtdegjeeuieenucevlhhushhtvghrufhiii gvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehlrghrrhihsehgrghrfhhivghlught vggthhdrtghomhdpnhgspghrtghpthhtohepuddpmhhouggvpehsmhhtphhouhhtpdhrtg hpthhtohepihhnthgvrhhnrghlsheslhhishhtshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id A67C129C006F; Thu, 20 Mar 2025 00:57:19 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: Tff1c7e423588aeea Date: Wed, 19 Mar 2025 23:56:59 -0500 To: "php internals" Message-ID: <14fab616-e660-403c-a932-8225cf629a6e@app.fastmail.com> In-Reply-To: References: Subject: Re: [PHP-DEV] PHP True Async RFC - Stage 2 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: larry@garfieldtech.com ("Larry Garfield") First, side note: When I said "Tim" in my earlier messages, I was in fac= t referring to Rowan. I do not know why I confused Tim and Rowan. My a= pologies to both Tim and Rowan for the confusion. On Tue, Mar 18, 2025, at 2:26 AM, Edmond Dantes wrote: > Hello, Larry. > >> >> First off, it desperately needs an "executive summary" section up at = the top.=20 >> There's a *lot* going on, and having a big-picture overview would hel= p a ton. (For >> examples, see property hooks[1] and pattern matching[2].) =20 >> > > I looked at the examples you provided, but I still don't understand=20 > what exactly I could put in this section. =20 > Key usage examples without explanation? > Do you think that would make the RFC better? I don=E2=80=99t really un= derstand=20 > how.=20 For a large RFC like this, it's helpful to get a surface-level "map" of = the new feature first. What it is trying to solve, and how it solves it= . Basically what would be the first few paragraphs of the documentation= page, with an example or three. That way, a reader can get a sort of m= ental boundary of what's being discussed, and then can refer back to tha= t when later sections go into all the nitty gritty details (which are st= ill needed). As is, there's "new" syntax being introduced for the first= time halfway through the document. I have a hard time mentally fitting= that into the model that the previous paragraphs built in my head. So as an outline, I would recommend: * Statement of problem being solved * Brief but complete overview of the new syntax being introduced, with m= inimal/basic explanation * Theory / philosophy / background that people should know (eg, the top-= down/bottom-up discussion) * Detailed dive into the syntax and how it all fits together, and the ed= ge cases * Implementation related details (this should be the first place you men= tion the Scheduler that doesn't exist, or whatever) >> Second, please include realistic examples. Nearly all of the examples= are contrived, >> > Which examples do you consider contrived, and why? =20 The vast majority of the examples are "print Hello World" and "sleep()",= in various combinations. That doesn't tell me how to use the syntax fo= r more realistic examples. There's a place for trivial examples, defini= tely, but also for "so what would I do with it, really?" examples. It s= hows what you expect the "best practices" to be, that you're designing f= or. >> The first non-foobar example includes a comment "of course you should >> never do it like this", which makes the example rather useless >> > Do you mean working with a closure that captures a reference to `$this= `? > But that has nothing to do with this RFC, either directly or=20 > indirectly. And it=E2=80=99s not relevant to the purpose of the exampl= e. =20 The Coroutine Scope Lifetime example. It says after it:=20 "Note: This example contains a circular dependency between objects, whic= h should be avoided in real-world development." Which, as above, means it is not helpful in telling me what real-world d= evelopment with this feature would look like. How *should* I address th= e use case in that example, if not with, well, that example? That's unc= lear. >> And the second is >> built around a code model that I would never, ever accept into a code= base, so it's >> again unhelpful. >> > > Why? =20 The second code block under "Coroutine local context". It's all a serie= s of functions that call each other to end up on a DB factory that uses = a static variable, so nothing there is injectable or testable. It has t= he same "should be avoided in real-world development" problem, which mea= ns it doesn't tell me anything useful about when/why I'd want to use loc= al context, whatever that is. >> So would the functions/keywords be shortcuts for >> some of the common functionality of a Scope object? >> > Were you confused by the fact that the `Scope` object has a `spawn`=20 > method? > (Which is semantically close to the operator?) > I understand that having both a method and an operator can create=20 > ambiguity, but it's quite surprising that it could be so confusing. =20 Yes, that, for example. It suggested in my mind that the `spawn` keywor= d would be an alias for currentScope()->spawn(). Whether that would be = wise or not I don't know, but if that wasn't your intent, then it was co= nfusing. > How should I have written about this? It's simply a part of reality as=20 > it is. Why did this cause confusion?=20 > Yes, I split this RFC into several parts because it's the only way to=20 > decompose it.=20 > It=E2=80=99s logical that this needs to be mentioned so that those who= haven=E2=80=99t=20 > followed the discussion can have the right understanding.=20 > What=E2=80=99s wrong with that?=20 I am fully in favor of explicitly "linking" RFCs together, such that eac= h sub-feature can be discussed separately. However, each RFC needs to, = on its own, be self-contained and useful. Maybe less useful than if the= whole set were passed, but at least useful on its own. Sometimes that means the individual RFCs are still quite large (eg, prop= erty hooks, which was split from aviz). Other times they're quite small = (eg, pipes, which is part one of like 4, all noted in Future Scope). Bu= t each RFC needs to "work" on its own. Consider: Suppose this RFC passed, but the follow-up to add a Scheduler = did not pass, for whatever reason. What does that leave us with? I thi= nk it means we have an approved RFC that cannot be implemented. That's = not-good. If this RFC adds a keyword "async" or "spawn" or whatever we end up with= , then that keyword needs to be able to do something useful with just th= e functionality approved in this RFC. Some additional functionality may= not be available until a later RFC, which makes the whole thing better,= but it at least still does something useful with the approved RFC. For example, I suspect all the context values bits could be punted to a = future RFC. Yes, that means some things won't be possible in the 1.0 ve= rsion of the feature; that's OK. It may mean designing the syntax in su= ch a way that it will evolve cleanly to include it later. That's also O= K. But whatever plumbing needs to exist for the user-facing functionali= ty to work (eg, the scheduler) needs to be there at the same time the us= er-facing functionality is. >> Are those >> standard terms you're borrowing from elsewhere, or your own creation? >> =20 > > Unfortunately, I couldn't find terminology that describes these models= .=20 > However, the RFC itself provides definitions. What is confusing to you= ?=20 Mainly that I wasn't sure if this was drawing on existing literature and= I should be googling for these terms or not. If there is no existing l= iterature then defining your own terms is fine, just be clear that's wha= t you're doing. >> I cannot really tell which one the "playpen" model >> would fit into. >> > > If we're talking about the "nursery" model in Python, there is no=20 > direct analogy because a *nursery is not a coroutine*, but rather a=20 > *Scope* in this RFC.=20 Yes, I meant nursery. (I have a 6 month old baby; all these baby-relate= d terms blend together in my head. :-) ) > In this context, the model in the RFC is essentially no different from=20 > nurseries in Python. That was not at all evident to me from reading it. > The key difference lies elsewhere. > To define the structure, two elements are used: > > =E2=80=A2 The coroutine itself > =E2=80=A2 An object of type *Nursery* or *Scope* > So in Python, coroutines work exactly the same way as in Go, and the=20 > *nursery* is an additional mechanism to ensure structured concurrency. > > In this RFC, there is a *nursery (Scope)*, but in addition to that,=20 > *coroutines themselves are also part of the structure*. > (So this RFC uses a stricter approach than Python) > > Does this mean it's not clear from the text? Yes, because I didn't get that message from it. (This is where a 10,000= foot overview early on would be helpful.) >> I honestly cannot see a use case at this point for starting coroutine= s in arbitrary scopes. >> > If we're talking about launching a coroutine in *GlobalScope*, then=20 > it's 99% likely to be an *anti-pattern*, and it might be worth removin= g=20 > entirely. It's the same as creating a global variable using `$GLOBAL[]= `. > However, if we're referring to a *pattern where a service defines its=20 > own `$scope`*, then this is probably one of the most useful aspects of=20 > this RFC. This is where more practical examples would be helpful. Eg, when and wh= y would a service define its own scope, and what are the implications? =20 >> Elsewhere in the thread, Tim noted that=20 >> we should unify the function call vs closure question. >> > > It would be great if this were possible, but so far, I haven't found a=20 > syntax that satisfies both requirements. > > Of course, the syntax could be unified like this: > > ```php > > spawn function($params): string use() { > }('param'); > > ``` > > and > > ```php > > function test($x); > spawn test($x); > > ``` > > But it looks unnatural... =20 > > Right now, I'm mentally close to the approach that Rowan_Tommins also=20 > described.: > > ```php > > spawn use($parameters): string {}; > spawn test($x); > ``` Let me ask this: With the spawn/start/whatever keyword, what is the expe= cted return value? Does it block until that's done? Do I get back a fu= ture? =20 If the mental model is "take a function call like you already had and st= ick a 'start new coroutine keyword on it'", then that leads to one set o= f assumptions and therefore syntax behavior. If it's more like "fork a = subprocess that I can communicate with later", that leads to a different= set of assumptions. On Tue, Mar 18, 2025, at 2:59 AM, Rowan Tommins [IMSoP] wrote: > I actually think what you're describing is very similar to the RFC,=20 > just with different syntax; but your examples are different, so you're=20 > talking past each other a bit. That is quite possible. Given the other comments above, I'd say likely. > The "request handler" use case could easily benefit from a=20 > "pseudo-global" scope for each request - i e. "tie this to the current=20 > request, but not to anything else that's started a scope in between". Potentially, though I would still question why it cannot just be explici= tly passed values. (All data flow is explicit; sometimes it's painfully= explicit. :-) ) --Larry Garfield