Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93011 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 85912 invoked from network); 30 Apr 2016 23:14:21 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Apr 2016 23:14:21 -0000 Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.54 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 74.125.82.54 mail-wm0-f54.google.com Received: from [74.125.82.54] ([74.125.82.54:38790] helo=mail-wm0-f54.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id E9/03-58459-A4C35275 for ; Sat, 30 Apr 2016 19:14:19 -0400 Received: by mail-wm0-f54.google.com with SMTP id g17so89022362wme.1 for ; Sat, 30 Apr 2016 16:14:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding; bh=ouMuwxGjrVLekKzawqS2AI781IFNPD1uQaCdNificLQ=; b=Ojlr89VFWFEnR3fexBJBQ2bSgJb9GOw8DrqxeTQa1Qcr7NNbs/msZ+u9I8Yn3CXT/S 8f3hw6h4NyEr0DdUTqbDgly6YybG0hrUCygRZXnQTqsJFfweNTpR1fJVYfB8RIK7iKHd 3cuUQBF9PFf+zB7SroUVN7bVmY49QU2mY1h4ErlnDlmQu1fFsRUPg0fiCCa1Pv0U3a6f 9ccht7wvTeO5HIVOpfBMKTSA66z/3A2TaOYj6AV3EkjHGZ/8bgXFZFHQ1RSNKDfYZkeX 0ZbSXsR3bq5yukTxJLrhR9ylcalSvBLrA9IOAiueKS5fZZ+rRaja2awMuRR7tG1eSPol O+og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=ouMuwxGjrVLekKzawqS2AI781IFNPD1uQaCdNificLQ=; b=UAnV2AP+HHnc+C+Pcae9Q6Bfdm3kFirSJJIdYLeNeZdr5n1yt9pfOJeNv/o9AWNEYE Z3B3d5graYCdwGFiTGtfaEEhw9q9YnYVTa61EeBVkeZIgAvXdMB77AtlmeY9KGRw5W/t M+NeSshj4UD4rw1EtsgQTYC5bALCZU6mClybwg9c+V/4tPkT6Fm+n8C6DNy5GOA1fIcC 57LpqspkX0cuvlAXuxn1UAua/WnBeM7Z2u9WLeje+r0O35aEQr68YzJFb4BZuUPm8fQX JxwKW98n/OuuQnqyjcYi7Mj+MT/16J5iTIcIKtlOCqlrdgJVBvgmzF37omalTdgsY+oe KLKg== X-Gm-Message-State: AOPr4FVsoplzqgO/9unRtF/OoqTZJX+s6M9Fa5ZbHH/mFTXAcmPSLLS7v0Pm8lczCt0CvQ== X-Received: by 10.194.9.201 with SMTP id c9mr28721779wjb.7.1462058056321; Sat, 30 Apr 2016 16:14:16 -0700 (PDT) Received: from [192.168.1.189] ([2.27.88.132]) by smtp.googlemail.com with ESMTPSA id az2sm16020239wjc.6.2016.04.30.16.14.15 for (version=TLSv1/SSLv3 cipher=OTHER); Sat, 30 Apr 2016 16:14:15 -0700 (PDT) To: internals@lists.php.net References: Message-ID: <4fc01507-3d07-2309-a4e4-4cad7325249b@gmail.com> Date: Sun, 1 May 2016 00:14:06 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] [RFC] Pipe Operator From: rowan.collins@gmail.com (Rowan Collins) On 29/04/2016 20:58, Sara Golemon wrote: > This is one of my favorites out of HackLang. It's pure syntactic > sugar, but it goes a long way towards improving readability. > https://wiki.php.net/rfc/pipe-operator I like this idea, for the same reason I like chained method calls - the code reads left to right, rather than inside to outside. One problem with that, though, is that the output from the whole expression ends up on the left, if you want to save it out somewhere. To take an example from the RFC: $ret = scandir($arg) |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$); Once you've read through this whole sequence of steps, you have to go right back to the beginning to find that the result is saved into "$ret". It's not clear to me whether the RHS in the current implementation can be an arbitrary expression, since all the examples use function calls at every step; would this be valid? scandir($arg) |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$) |> ($ret = $$); Even if it is, it looks a bit ugly; what about adding an extra operator for assignment, like "|>=" or "|=>"? scandir($arg) |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$) |=> $ret; I think this would also improve the situation around debugging and error-handling, because you could more freely mix piped and non-piped code by "breaking the chain" with an assigment. Let's say I want to add a condition just before getFileArg(); with the current version I've got to: - go to the beginning of the chain, and assign to something other than $ret - go to where I want to break the chain, and reintroduce the $ret assignment - add my check in the gap, using the variable I just added at the beginning of the chain $fileList = scandir($arg) |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$); if ( someCheck($fileList) { something(); } $ret = getFileArg($$) |> array_merge($ret, $$); The syntax is fighting me here, making me jump around the code. But if assignment was always on the end of the chain, I would only need to make changes at the point where I was breaking the chain. The basic pattern would be: |=> $tempVar; // terminate the chain and capture the value // do stuff with $tempVar $tempVar // restart the chain So: scandir($arg) |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |=> $fileList; if ( someCheck($fileList) { something(); } $fileList |> getFileArg($$) |> array_merge($ret, $$) |=> $ret; If I don't need the condition any more, I can delete lines 4 to 8, and I've got back my original chain. Again, I'm not clear from the RFC if it's currently valid to use "return" in a piped expression, but it makes sense to me for the same reasons outlined above. This example is from the Hack docs, where it puts the "return" on the left, breaking the flow: return $arr |> array_map($x ==> $x->getNumber(), $$) |> array_filter($$, $x ==> $x % 2 == 0) |> count($$); To me, that reads better as: $arr |> array_map($x ==> $x->getNumber(), $$) |> array_filter($$, $x ==> $x % 2 == 0) |> count($$) |> return $$; Personally, I'd quite like it if the chain *had* to have a left-to-right form like this, and always constituted a statement, not an expression. Regards, -- Rowan Collins [IMSoP]