Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130061 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 lists.php.net (Postfix) with ESMTPS id 0CC301A00BC for ; Sun, 8 Feb 2026 19:19:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1770578391; bh=sRLR7ifckokTH/3FpoC+JCjEY/cmud9RdADPWDiRbcY=; h=Date:Subject:To:References:From:In-Reply-To:From; b=I5YKJv77Zni+Ak2y3P0zzY72aqovRGb0KebxqN33NcAf/p6gRIgszlpMZvXp6P2m8 /i/nvl/bfJ/yCe7PD5kEtUMLE7YP13g+JKADecKaZEFtv2nRrTWXPFYBcu285JXX9Q ZmdehR2CmzBHU8Uq6Ck/IuWkSec+ySubiJJpjy04EwObBF8YOxZgDyprpWESePgyBU RcPqOvzHUujsJ7+qyelpcZVHX9+UX+7X0qONsLA+0OAqLaQkLBcJ7iowpterXNvJD3 iJ9g/0cfJdYDU9l2uHg6NxZgzaisjI/W8fjiWkFOqtp4R/Uh6gjMkpaznpmRD2WMqq pKm6ULNK/0ffw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 9A52D180050 for ; Sun, 8 Feb 2026 19:19:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,T_SPF_TEMPERROR autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.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 ; Sun, 8 Feb 2026 19:19:47 +0000 (UTC) Received: by mail-lj1-f171.google.com with SMTP id 38308e7fff4ca-385c6c727fcso30384391fa.3 for ; Sun, 08 Feb 2026 11:19:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770578381; x=1771183181; darn=lists.php.net; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id:from :to:cc:subject:date:message-id:reply-to; bh=Z6kbfnJ8uy0ayVQdVuuJrTIniktgjssw/5wqUaOpOxc=; b=BqnGeRy6Va7ZqLmhDx9MT1i5++lX6FGi5l/aMjX0fhmH27T8uCL7j7VcjWjBZAMTLS qkgfkG5YXYIj8HIkv91e0xvtm4QeLzN0xrkfq4PnlS5ottg6CacdoHRjbhF+S9ZOoE7+ jMPZj2OBHbMnsUDa6VUjLjNn37m010JoW7lr9Uh6LQSFCELnq/f3TmpgWRLgqcAdPF9Y a27TNNK5IcfMSmSAVA/7pOLJNZQkijeIe06wWXAq7XpAUerKYBcdEj6bAcNgD9crWp59 9CnqwLusRhGzYZNd2d824tG0ULFZ7vs1odJErqZbUrlJLWq3MnNE5n1wzRGzPOxL14bu RIjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770578381; x=1771183181; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Z6kbfnJ8uy0ayVQdVuuJrTIniktgjssw/5wqUaOpOxc=; b=VQIuNUExqHC8VMCfhbrR7epWS9vt1VKAxqCPb34Jz8ryDOv8R0CJOR/6R1VgbRcb9N Q3OzyIT0DHE+RZilSVzszexuSGLP5kU8gr5X8A881fteTaqhN9serbNVKbkIl1Ahi25l NPJJ5W6ARe5Nw6axcCt6zfypblZ5nRgOjlOQNO8Pmea1+iJ8dxABRqhR2yhfvokm129T I5wprx0tEA3wenysJmd4CZcTn2YZeAGSVvGiBfgTSUvwUk9HBojm64/5vYzTWbb+LkAh yKMz808fI4qiUH/mK3/tPZbi6kTX3IJ3GHQPLW3fNwXHEjk2++qs9i6IPNIWgJmquwnA JFYg== X-Forwarded-Encrypted: i=1; AJvYcCXn4f0ADyG2+EvzhTqOZCnRmPe3BySm9No1k/g+FkwpMN1rHoNQqucr47ZFXa7AphBH9rPAo9+uJqg=@lists.php.net X-Gm-Message-State: AOJu0Yw0GaetvSfMNargrwYj28+oEffJF/c0O+e5aMTMCQoMYwwRjH6x 648LjqXkpv0Yf8NZ7hTWJoc969um48I5lxJNv+Fu1tFbhgP4Hr9otkJYIUOqNg== X-Gm-Gg: AZuq6aKaupiEHqvNKesTpu9ShvmogxKAmq5/g2faAywg9rW8GdzrdcVm/yF96IKwLAu qLmjdh51AmxWHUzyrNg0D6bRvbLIsWHrhr5OPbA8BL/kREQx3n3+Slzpm1e8iMp+DyOkWLa5jPU oy1aaXBvOPaFhLjTJqkILDczZ4S0TSd9FzLh6b5mh0gx+NhAYh0NxkyHQC1SXKqCEr8+nUquKfh ZsmxMJlG1tOOID5iBjdKk9+IdDSf6n+u1gEINo9avmX7T7dKE5PMaMxZ/1ZBabW9gt+wx3I7//P /yqjZJIoMXmTsCev/ANFf7JZgfX7Bd6mWqG1t7h35iLmxCTL6A8VE3lPl/putO7s5O+DKLKOnGf ms+faGIvWQLq0Ny0+HWfgGtUw3abZAmE2cuc+iPyaROYP3JEqAkiBC0KhsOaIZZ4WDDoQ28A8mz 3KqFL1YxwphQ0z9ZgA7GPJruE= X-Received: by 2002:a05:6512:b92:b0:59e:39af:a710 with SMTP id 2adb3069b0e04-59e4515a47dmr3030837e87.34.1770578380481; Sun, 08 Feb 2026 11:19:40 -0800 (PST) Received: from [192.168.1.16] ([46.181.226.137]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59e44cf6f3bsm2081058e87.18.2026.02.08.11.19.39 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 08 Feb 2026 11:19:40 -0800 (PST) Message-ID: <89a586d3-6eee-45eb-9a2d-cb432589aaae@gmail.com> Date: Mon, 9 Feb 2026 02:19:39 +0700 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] [RFC] Pipe to return To: Rob Landers , internals@lists.php.net, =?UTF-8?Q?Tim_D=C3=BCsterhus?= References: <53c17181-caa4-41a3-b4ab-93069e6bb47b@gmail.com> <58b0417b-15fb-44cd-aaf1-7d88c291c491@app.fastmail.com> Content-Language: en-US In-Reply-To: <58b0417b-15fb-44cd-aaf1-7d88c291c491@app.fastmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: vadim.dvorovenko@gmail.com (Vadim Dvorovenko) 31.01.2026 20:45, Rob Landers: > I get I could just ... not do that ... but since this seems to be > about cognitive load, I think this would actually add additional > cognitive load instead of removing it. Often, you need to find where > the function returns; more often than you need to read actual pipes. 03.02.2026 22:13, Tim Düsterhus: > That said, I agree with the others that I find the proposal a step > backwards in terms of readability. Having the `return` at the start of > the line is a clear indicator that the function ends there and it is > only a “single bit” of information I have to keep in mind while I > continue reading until I find the semicolon ending the statement. It > is also consistent with how assignments - the other primary use case > for pipes - start with the target variable and the equals before the > “pipe expression”. I think it would not be wrong to think of `return` > as “assigning to the return value”. Thanks for these comments. I find them among the most valuable in this discussion. They really made me think for a long time and experiment a lot. To discuss them, I've been going through and trying to come up with different code options. Unfortunately, there aren't any successful examples yet in the real projects and libraries I work with. If you could provide links to repositories where pipe operator is actively used, I'd be very grateful. So for now I apologize for the fictitious example. Let's take this complex function     function process_request($request)     {         if ($request instanceof ManageEmployeeRequest) {             if ($request instanceof CreateEmployeeRequest) {                 return $request |> logRequest(...) |> validateCreateEmployeeRequest(...) |> processCreateEmployee(...) |> formatEmployeeDataAsArray(...) |> convertArrayToJsonResponse(...);             } elseif ($request instanceof UpdateEmployeeRequest) {                 return $request |> logRequest(...) |> validateUpdateEmployeeRequest(...) |> processUpdateEmployee(...) |> formatEmployeeDataAsArray(...) |> convertArrayToJsonResponse(...);             } elseif ($request instanceof DeleteEmployeeRequest) {                 $request |> logRequest(...) |> validateDeleteEmployeeRequest(...) |> processDeleteEmployee(...);                 return [] |> convertArrayToJsonResponse(...);             } else {                 throw new InvalidArgumentException("Unknown client request type");             }         }         if ($request instanceof ManageClientRequest) {             if ($request instanceof CreateClientRequest) {                 return $request |> validateCreateClientRequest(...) |> processCreateClient(...) |> formatClientDataAsArray(...) |> convertArrayToJsonResponse(...);             } elseif ($request instanceof UpdateClientRequest) {                 return $request |> validateUpdateClientRequest(...) |> processUpdateClient(...) |> formatClientDataAsArray(...) |> convertArrayToJsonResponse(...);             } elseif ($request instanceof DeleteClientRequest) {                 $request |> validateDeleteClientRequest(...) |> processDeleteClient(...);                 return convertArrayToJsonResponse([]);             } else {                 throw new InvalidArgumentException("Unknown client request type");             }         }         throw new InvalidArgumentException("Unknown request type");     } When we read this function, we are actually more interested in the structure of conditions and returns than in the actual actions. In this case, of course, return at the beginning of the line is indeed more readable. Here I completely agree with you. But in real life we ​​won't use such long lines and the chain will be split into several lines. Here I used different code styles in one block for clarity.     function process_request($request)     {         if ($request instanceof ManageEmployeeRequest) {             if ($request instanceof CreateEmployeeRequest) {                 $request                     |> logRequest(...)                     |> validateCreateEmployeeRequest(...)                     |> processCreateEmployee(...)                     |> formatEmployeeDataAsArray(...)                     |> convertArrayToJsonResponse(...)                     |> return;             } elseif ($request instanceof UpdateEmployeeRequest) {                 return                     $request                         |> logRequest(...)                         |> validateUpdateEmployeeRequest(...)                         |> processUpdateEmployee(...)                         |> formatEmployeeDataAsArray(...)                         |> convertArrayToJsonResponse(...);             } elseif ($request instanceof DeleteEmployeeRequest) {                 $loggedRequest = logRequest($loggedRequest);                 $validatedRequest = validateDeleteEmployeeRequest($loggedRequest);                 processDeleteEmployee($validatedRequest);                 $response = convertArrayToJsonResponse([]);                 return $response;             } else {                 throw new InvalidArgumentException("Unknown client request type");             }         }         // ...     } In my case, the IDE brightly highlights 'if', 'elseif', and 'return' keywords. In this version, I clearly see the return in the first two blocks, despite its different placement. The 'return' in the third block stands out the least; it blends in with the preceding text because there is no indentation. But when I'm composing a letter, I don't have syntax highlighting, but the feeling is the same. The third block looks more like a chain of actions. Of course, it's written in imperative style. The first block also looks like a chain of actions. Vision very quickly stops paying attention to `|>`. Moreover, it fits seamlessly into the conditions structure. It's clear that this chain of transformations is executed under these very conditions. And here it seems to me very fortunate that after reading the block to the end, we see return, and we don’t need to look up 6 lines above to remember why we performed all these actions. I myself reread the second block several times, trying to understand whether it really is more convenient to read. But every time I read the chain of actions to the end, I caught myself thinking that I didn’t want to go back to check if there was a ‘return’ there. On the contrary, during the time I was working with this example, my brain developed a rule, and seeing a vertical chain of '|>', I immediately began to look at the end of the block to understand whether there is a return at the end. It's like looking at the first and last lines of a third block, skipping over everything in between. But with `|>`, your eye kind of slides down them, and you get to `|> return;` much faster. I also noticed that when I look at the second block, my vision selects the block starting with `$request`. For some reason it crops the `return` located to the left and above. I think this is because it is a keyword that has ceased to carry meaning for us, and we perceive it as a punctuation mark, rather than as carrying meaning.