Hi! > From: ocram...@gmail.com > > I would say that this makes the entire functional approach: > > 1. more readable > 2. easier to debug (woah, we can haz line numbers for failures!) > > Here's the pseudo-code for a typical request/response dispatch cycle: > > $request = getGlobals() > |> parseRequest($$) > |> buildPsr7Request($$); > > $response = loadConfig() > |> buildDic($$) > |> getApp($$) > |> getRouter($app) > |> getDispatcher($$, $request) > |> dispatchBusinessLogic($$, $request, new Response()) > |> renderResponse($$) > |> buildPsr7Response($$) > |> emit($$); > > Here's what it would look like with a separate approach (more > business-oriented): > > buildRequest() // (basically the first part of the previous example here) > |> validate($$) > |> convertToCommand($$) > |> execute($$) > |> convertToViewModel($$) > |> render($$) > |> convertToHttpResponse($$) > |> emit($$) > > I think this is much more readable/clear than any event-driven or > procedural approach. > We know exactly what is going on, we will get clear stack traces (this > could need some fine-tuning of the current PR - I didn't try it out yet) > and we will be able to introduce intermediate steps with ease. In addition > to all that, this will ease reactive programming by a lot, as piping is a > natural fit for streams and all abstractions around streams. > > The syntax is also already effective in F# (you can write very expressive > and easy to understand code with it) and now also landed in Hack. > > I'd say +10 to this proposal :D
I have to agree with this. The examples in the RFC probably don't show the best examples of it - the pipe operator really clarifies code when nesting numerous simple function calls. Quoting the example above: $response = loadConfig() |> buildDic($$) |> getApp($$) |> getRouter($app) |> getDispatcher($$, $request) |> dispatchBusinessLogic($$, $request, new Response()) |> renderResponse($$) |> buildPsr7Response($$) |> emit($$); Without the pipe operator, it could look like the following: $config = loadConfig(); $dic = buildDic(config); $app = getApp($dic); $router getRouter($app); $dispatcher = getDispatcher($router, $request); $businessResponse = dispatchBusinessLogic($dispatcher, $request, new Response()); $renderedResponse = renderResponse($businessResponse); $psr7Response = buildPsr7Response($renderedResponse); $response = emit($psr7Response); That's a lot of unnecessary assignments, however, and the variable names don't even provide any additional readability benefits because the function names are already self-documenting. More likely, the above code would be written as numerous nested function calls: $dispatcher = getDispatcher(getRouter(getApp(buildDic(loadConfig())))); $response = emit(buildPsr7Response(renderResponse(dispatchBusinessLogic($dispatcher, $request, new Response())))); Having to dissect expressions like the above from inside-out is not a natural way to read how the operations are actually occurring though. It's far easier to read them from left-to-right or top-to-bottom, and this is where the advantages of the pipe operator can really be seen. So I'm definitely +1 on this feature - it's something I really miss from Elixir. -Tom -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php