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

Reply via email to