[erlang-questions] Pipe Operator in Erlang?

Dmitry Belyaev <>
Thu Jul 9 23:26:56 CEST 2015


I'm surprised nobody mentioned erlando: https://github.com/rabbitmq/erlando
-- 
Best wishes,
Dmitry Belyaev

On 10 July 2015 3:44:55 AM AEST, Fred Hebert <> wrote:
>On 07/09, José Valim wrote:
>>I agree with the general feelings of the thread. F# relies on
>currying.
>>Elixir relies on macros (it is actually closer to the thread operator
>found
>>in some lisps).
>>
>>Also F# has most of its standard library expecting the "subject" as
>last
>>argument (due to currying). Elixir defaults to the first argument.
>Erlang,
>>for better or worse, has them mixed (see binary and lists modules).
>>
>
>I agree with this. The only workable form I could imagine could go 
>something like this with macros, without major changes to the language:
>
>pipe(Init, a(_, X), b(Y, _), c(_, _, 41.12)), where '_' gets replaced
>by 
>the threaded in 'Init' state. The obvious problem is lack of 
>composition:
>
>pipe(Init, pipe(Init2, a(_))) where you can't know if a(_) refers to 
>Init or Init2 at a glance without knowing precise evaluation rules.
>
>Generally I haven't felt I missed this feature too much in Erlang. In 
>the cases where it could really be nice, I resorted to using:
>
>    pipe(Init, Funs) ->
>        lists:foldl(fun(F, State) -> F(State) end, Init, Funs).
>
>    pipe(Init,
>         [fun(S) -> set(S, 230) end,
>          fun(S) -> update(S) end,
>          fun(S) -> output(S), S end]).
>
>Obviously, one could easily come and swoop in with a macro:
>
>    pipe(Init, $$,          % $$ is replaced by 'Init'
>         set($$, 230),
>         update($$),
>         fun() -> output($$), $$ end)
>
>The problem is that composition is not obvious:
>
>    pipe(Init, $$,
>         pipe($$, $_,
>              set($_, 230),
>              update($_),
>              fun() -> output($$), $_ end))
>
>In that case, the last 'output($$)' would try to print the literal '$$'
>
>value instead of the substituted one given underneath it all, it's 
>equivalent to:
>
>    pipe(Init, [fun(S) -> pipe(S, [...]) end]).
>
>Woops! But what's cool? Add in a maybe pipe!
>
>    maybe_pipe(Init, Funs) ->
>        %% use throws and catches if you wanna go faster
>        lists:foldl(fun(F, {ok, State}) -> F(State)
>                    ;  (F, {error, Err}) -> {error, Err} end,
>                    Init,
>                    Funs).
>
>And with the same set of parse transforms you can change:
>
>    f(X0) ->
>        case g(X0) of
>            {ok, X1} ->
>                case h(X1) of
>                    {ok, X2} -> {ok, X2};
>                    Err = {error, _} -> Err
>                end;
>            Err = {error, _} ->
>                Err
>        end.
>
>Into:
>
>    f(X0) ->
>        maybe_pipe(X0, $$, g($$), h($$)).
>
>Which translates to:
>
>    f(X0) ->
>        maybe_pipe(X0,
>                   [fun(X) -> g(X) end,
>                    fun(X) -> h(X) end]).
>
>And all of this is doable today in library code for or from anyone, 
>doesn't fundamentally change the shape of Erlang, although it will 
>definitely be more confusing for newcomers or people not familiar with 
>the concept.
>
>All it needs is someone angry enough to do it. I don't believe (from 
>doing experiments like Hubble[1]) that it's particularly hard.
>
>Regards,
>Fred.
>
>[1]: https://github.com/ferd/hubble
>
>_______________________________________________
>erlang-questions mailing list
>
>http://erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150710/d98a18c4/attachment.html>


More information about the erlang-questions mailing list