Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127034 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 B0B361A00BC for ; Thu, 3 Apr 2025 17:06:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1743699867; bh=INkgTcmAWEZ42j7n0pnXoKDgFFiKgbMCOVNrIDtjUKg=; h=Date:From:To:In-Reply-To:References:Subject:From; b=Ebo+ke5+1ZA90KisZjQgkqp2YSXxxbwNdVjY9hCQ2YBhT0QKaEWlm2Nw1NA49PNVb mTcByLjR/t8FZsOEUTEJ36Joo6gjbI3a7lA7BVo4397rVMhfXxYa7VlxklBUKUqrfq CgnRL3z5xr+/ZoHdCikvHyXvCSb3b5/HKUvc4gA45ZZMc7T/YJwLmIoP1zZLgDSPUo 5HkR2CTWJeCTumThE2LESsm7bpkqh+tB8AJwZ7ryv1Mkth2Eqw/OEPBM+ZJAnaNTS+ NAU0ior2489hQTe8hq5ftHwzCxllQq+/recQnXiqpENLGLWGlpTYFQJlGf5oxBEAdT hggFQe2n6cPhA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id AE7131801E1 for ; Thu, 3 Apr 2025 17:04:25 +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, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout-b7-smtp.messagingengine.com (fout-b7-smtp.messagingengine.com [202.12.124.150]) (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, 3 Apr 2025 17:04:25 +0000 (UTC) Received: from phl-compute-12.internal (phl-compute-12.phl.internal [10.202.2.52]) by mailfout.stl.internal (Postfix) with ESMTP id 331A811401A2 for ; Thu, 3 Apr 2025 13:06:51 -0400 (EDT) Received: from phl-imap-06 ([10.202.2.83]) by phl-compute-12.internal (MEProxy); Thu, 03 Apr 2025 13:06:51 -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=fm2; t=1743700011; x=1743786411; bh=qqqqUX9Xk/GqCbx3FPDVp djo/63wQUyKxPe+7KJyTgw=; b=CjFX9QhXJDdxqB5pPKv7/QdvirHUh01FmTSL/ B4DBqvZSiKAH+J4cjilGERhSoBo/xBNwT2V3g8P932tyfFuCtuFGVg+uMJMyiPlg lWcPB7f/8rUP9xrxDzRVbdYfo+Hkoel6dK521Ney3snJufkaicDFqthlJHjK04Ht 9wLVvk3LvUuutn2WWcUCVu/5mISjgkM7XyDNQGbsymDmYBKQLOJWF1G+j0u2bIPE YKx8BCo+kJzFyUbEGi82ENBhJnONP3O38B1ahBwdq8A0rIPcnqN28+oIvRY70K79 B7C3/osAfCWP5YmNFTW3tu2saPeXX5vjydAJeLSn7nvQnDhIw== 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=fm2; t=1743700011; x=1743786411; bh=q qqqUX9Xk/GqCbx3FPDVpdjo/63wQUyKxPe+7KJyTgw=; b=eYaQb7ypjxpOhs4Ng drI+RqyW4aBL23COaoC/Z7fk8LRomnbgLIpDe02ezGgy+EzOtwfcVDng87cZoNK9 VNzaHAUo0vTkdpHuqAOA9WbVCa+DoEu/PdCi++mus8WHsfIqbHthFwtv/chFBKWP Yirzzcygdu2vbSAVz0fG5zFgIp5qqMsyjwBdU3oT1FtOvg70OBZl/0h05JxDYbre 66P1coHO/IrIJD4rSRFEsncgfY6TGHpydX47JaTsXkyRBnwMJH0gQfxfo2CBAJIW 4X5UL5otMQGx3S3HN4tknAHP35VLpC5mwkcCjvLrOAaH+0GkueVlHTuMzvIhUF5O 7wEmQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddukeeludduucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvffkjghfufgtgfesthhqredtredt jeenucfhrhhomhepfdfnrghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrh hfihgvlhguthgvtghhrdgtohhmqeenucggtffrrghtthgvrhhnpeehjeefvefgfeduteff ffdvheeiudekieefleevvdduiefgkeehvdevheffvdegteenucffohhmrghinhepghhith hhuhgsrdgtohhmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhf rhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhmpdhnsggprhgtphhtth hopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehinhhtvghrnhgrlhhssehl ihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id BC42C29C0072; Thu, 3 Apr 2025 13:06:50 -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: Tb59d627fb5f6e7a2 Date: Thu, 03 Apr 2025 12:06:29 -0500 To: "php internals" Message-ID: <7e2a3dea-aaaf-4427-b1b2-32c568af8b77@app.fastmail.com> In-Reply-To: <92b7f1ea-900b-4438-bed7-3fd766bb2d61@rwec.co.uk> References: <5efa2f02-dd1d-4d59-ae07-c75f193b4096@app.fastmail.com> <92b7f1ea-900b-4438-bed7-3fd766bb2d61@rwec.co.uk> Subject: Re: [PHP-DEV] [RFC] Pipe Operator (again) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: larry@garfieldtech.com ("Larry Garfield") On Thu, Apr 3, 2025, at 6:58 AM, Rowan Tommins [IMSoP] wrote: > On 03/04/2025 08:22, Larry Garfield wrote: >> However, it also received significant pushback off-list from folks wh= o felt it was too much magic. I don't want to torpedo pipes on over-rea= ching. But without feedback from other voters, I don't know if this is = over-reaching. Is it? Please, someone tell me which approach you'd be = more willing to vote for. :-) > > > At first, I thought Ilija's example looked pretty neat, but having=20 > thought about it a bit more, I think the "first-arg" approach makes a=20 > handful of cases nicer at the cost of a lot of magic, and making other=20 > cases worse. > > > The right-hand side is magic in two ways: > > 1) it looks like an expression, but actually has to be a syntactic=20 > function call for the engine to inject an argument into > > 2) it looks like it's calling a function with the wrong arguments > > If we have a special case where the right-hand side *is* an expression= ,=20 > evaluated as a single-argument callable/Closure, that's even more scop= e=20 > for confusion. [cf my thoughts in the async thread about keeping the=20 > right-hand side of "spawn" consistent] > > > The cases it makes nicer are where you are chaining existing functions=20 > with the placeholder as first (but not only) parameter. If you want to=20 > pipe into a non-first parameter, you have a few options: > > a) Write a new function or explicit wrapper - equally possible with=20 > either option > > // for first-arg chaining: > function swapped_explode(string $string, string $separator): string {=20 > return explode($separator, $string); } > $someChain |> swapped_explode(':'); > > // for only-arg chaining: > function curried_explode(string $separator, string $string): callable = {=20 > return fn(string $string) =3D> explode($separator, $string); } > $someChain |> curried_explode(':'); > > b) Use an immediate closure as the wrapper - only-arg chaining seems b= etter > > // first-arg chaining > $someChain |> fn($string) =3D> explode(':', $string)(); > > // first-arg chaining with special case syntax for closures > $someChain |> ( fn($string) =3D> explode(':', $string) ); > > // for only-arg chaining: > $someChain |> fn($string) =3D> explode(':', $string); > > c) Use a new partial application syntax - same problem as immediate cl= osure > > // for first-arg chaining > $someChain |> explode(':', ?)(); > > // or with overloaded syntax > $someChain |> ( explode(':', ?) ); > > // for only-arg chaining > $someChain |> explode(':', ?); > > > It's also quite easy to write a helper for the special-case of=20 > "partially apply all except the first argument": > > function partial_first(callable $fn, mixed ...$fixedArgs): callable { > =C2=A0=C2=A0=C2=A0 return fn(mixed $firstArg) =3D> $fn($firstArg, ...= $fixedArgs); > } > > // first-arg chaining > $someChain |> array_filter(fn($v, $k) =3D> $k =3D=3D=3D $v, ARRAY_FILT= ER_USE_BOTH); > > // native partial application > $someChain |> array_filter(?, fn($v, $k) =3D> $k =3D=3D=3D $v,=20 > ARRAY_FILTER_USE_BOTH); > > // workaround > $someChain |> partial_first(array_filter(...), fn($v, $k) =3D> $k =3D=3D= =3D $v,=20 > ARRAY_FILTER_USE_BOTH)); Writing higher order functions to simulate first-arg is indeed quite str= aightforward. The RFC has some simple examples, and I've written a whol= e bunch of more robust ones here: https://github.com/Crell/fp/blob/master/src/array.php https://github.com/Crell/fp/blob/master/src/string.php The issue is performance. With foo(...), foo(?, 'bar'), or implicit fir= st-arg, it's fairly straightforward to compile it down to a normal funct= ion call so there's no runtime cost. If you have an expression that pro= duces a callable that gets used, that cannot be optimized away. So we could get this resulting syntax with either higher order user-spac= e functions or with auto-first-arg: $foo=20 |> map($fn1)=20 |> filter($fn2)=20 |> implode(','); However, if map() is a higher order function that returns a unary callab= le, there are two function invocations involved. If it's custom syntax = that turns into map($foo, $fn1), then it's only one function invocation. So if we expect higher order functions to be common (and I would probabl= y mainly use them myself), then it would be wise to figure out some way = to make them more efficient. Auto-first-arg is one way. "Suck it up an= d use PFA with the ?" is another way that would work, but be less ergono= mic. I'm not sure of other options off hand. --Larry Garfield