Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92975 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 99810 invoked from network); 30 Apr 2016 10:00:07 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Apr 2016 10:00:07 -0000 Authentication-Results: pb1.pair.com header.from=tpunt@hotmail.co.uk; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=tpunt@hotmail.co.uk; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain hotmail.co.uk designates 157.55.2.92 as permitted sender) X-PHP-List-Original-Sender: tpunt@hotmail.co.uk X-Host-Fingerprint: 157.55.2.92 dub004-omc4s17.hotmail.com Received: from [157.55.2.92] ([157.55.2.92:62470] helo=DUB004-OMC4S17.hotmail.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 97/95-58459-42284275 for ; Sat, 30 Apr 2016 06:00:06 -0400 Received: from DUB129-W24 ([157.55.2.71]) by DUB004-OMC4S17.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Sat, 30 Apr 2016 03:00:01 -0700 X-TMN: [DlHI4VtQFZdIHM/TQBiq3wAwwspr9xtN] X-Originating-Email: [tpunt@hotmail.co.uk] Message-ID: To: Marco Pivetta , Stanislav Malyshev CC: Sara Golemon , PHP internals Date: Sat, 30 Apr 2016 11:00:01 +0100 Importance: Normal In-Reply-To: References: ,<8ea990da-1fe7-256c-4e08-0b30715c8e8a@gmail.com>, Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginalArrivalTime: 30 Apr 2016 10:00:01.0882 (UTC) FILETIME=[0FDD7BA0:01D1A2C7] Subject: RE: [PHP-DEV] [RFC] Pipe Operator From: tpunt@hotmail.co.uk (Thomas Punt) Hi!=0A= =0A= > From: ocramius@gmail.com=0A= >=0A= > I would say that this makes the entire functional approach:=0A= >=0A= > 1. more readable=0A= > 2. easier to debug (woah=2C we can haz line numbers for failures!)=0A= >=0A= > Here's the pseudo-code for a typical request/response dispatch cycle:=0A= >=0A= > $request =3D getGlobals()=0A= > |> parseRequest($$)=0A= > |> buildPsr7Request($$)=3B=0A= >=0A= > $response =3D loadConfig()=0A= > |> buildDic($$)=0A= > |> getApp($$)=0A= > |> getRouter($app)=0A= > |> getDispatcher($$=2C $request)=0A= > |> dispatchBusinessLogic($$=2C $request=2C new Response())=0A= > |> renderResponse($$)=0A= > |> buildPsr7Response($$)=0A= > |> emit($$)=3B=0A= >=0A= > Here's what it would look like with a separate approach (more=0A= > business-oriented):=0A= >=0A= > buildRequest() // (basically the first part of the previous example here)= =0A= > |> validate($$)=0A= > |> convertToCommand($$)=0A= > |> execute($$)=0A= > |> convertToViewModel($$)=0A= > |> render($$)=0A= > |> convertToHttpResponse($$)=0A= > |> emit($$)=0A= >=0A= > I think this is much more readable/clear than any event-driven or=0A= > procedural approach.=0A= > We know exactly what is going on=2C we will get clear stack traces (this= =0A= > could need some fine-tuning of the current PR - I didn't try it out yet)= =0A= > and we will be able to introduce intermediate steps with ease. In additio= n=0A= > to all that=2C this will ease reactive programming by a lot=2C as piping = is a=0A= > natural fit for streams and all abstractions around streams.=0A= >=0A= > The syntax is also already effective in F# (you can write very expressive= =0A= > and easy to understand code with it) and now also landed in Hack.=0A= >=0A= > I'd say +10 to this proposal :D=0A= =0A= I have to agree with this. The examples in the RFC probably don't show the= =0A= best examples of it - the pipe operator really clarifies code when nesting= =0A= numerous simple function calls. Quoting the example above:=0A= =0A= $response =3D loadConfig()=0A= =A0|> buildDic($$)=0A= =A0|> getApp($$)=0A= =A0|> getRouter($app)=0A= =A0|> getDispatcher($$=2C $request)=0A= =A0|> dispatchBusinessLogic($$=2C $request=2C new Response())=0A= =A0|> renderResponse($$)=0A= =A0|> buildPsr7Response($$)=0A= =A0|> emit($$)=3B=0A= =0A= Without the pipe operator=2C it could look like the following:=0A= =0A= $config =3D loadConfig()=3B=0A= $dic =3D buildDic(config)=3B=0A= $app =3D getApp($dic)=3B=0A= $router getRouter($app)=3B=0A= $dispatcher =3D getDispatcher($router=2C $request)=3B=0A= $businessResponse =3D dispatchBusinessLogic($dispatcher=2C $request=2C new = Response())=3B=0A= $renderedResponse =3D renderResponse($businessResponse)=3B=0A= $psr7Response =3D buildPsr7Response($renderedResponse)=3B=0A= $response =3D=A0emit($psr7Response)=3B=0A= =0A= That's a lot of unnecessary assignments=2C however=2C and the variable name= s=0A= don't even=A0provide any=A0additional readability benefits because=A0the=A0= function=0A= names=A0are already self-documenting.=0A= =0A= More likely=2C the above code would be written as numerous nested function= =0A= calls:=0A= =0A= $dispatcher =3D=A0getDispatcher(getRouter(getApp(buildDic(loadConfig()))))= =3B=0A= $response =3D=A0emit(buildPsr7Response(renderResponse(dispatchBusinessLogic= ($dispatcher=2C=A0$request=2C new Response()))))=3B=0A= =0A= Having to dissect expressions like the above from inside-out is not a natur= al=0A= way to read how the operations are actually occurring though. It's far easi= er=0A= to read=A0them from left-to-right or top-to-bottom=2C and this is where the= =0A= advantages=A0of the pipe operator can really be seen.=0A= =0A= So I'm definitely +1 on this feature - it's something I really miss from El= ixir.=0A= =0A= -Tom =