Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
by Oleg Tarasenko
This blog suggests an alternative means by which you can structure your programs, inspired by the Elixir pipe macro â|>â but without making use of the dreaded parse transforms using my tiny epipe library, which I have recently written. Epipe itself is inspired by this article published by Scott Wlaschin.
Getting started
Letâs perform a small practical task which will demonstrate this railway approach to functional programming.
Consider the case where weâre building a POP3 email client using Erlang. Our goal is to implement a control flow for establishing connections with a POPÂ server.
This diagram illustrates the steps needed to accomplish this action:
First, letâs build a function implementing the connection functionality:
connect(Addr, Port, ConnOptions, User, Password) -> {ok, Socket} = ssl:connect(Addr, Port, ConnOptions), ok = receive_greetings(Socket), ok = send_user(Socket, User), ok = send_password(Socket, Password).
The code above is very beautiful, only four lines of code and weâre done! But wait⊠the implementation above is very much a best case scenario. Obviously we need to add some error handling in order to to deal with edge cases :(. I mean, âwhat could possibly go wrongâ?
Adding error handling
Letâs summarise all possible edge cases on the diagram below:
Letâs add the error handling code, and see how it looks now!
Spoiler: The example below is trivial and can be beautified by splitting the operations into separate functions but the nested case statements are unavoidable.
connect(Addr, Port, ConnOptions, User, Password) -> case ssl:connect(Addr, Port, ConnOptions) of {ok, Socket} -> case receive_greetings(Socket) of ok -> case send_user(Socket, User) of ok -> case send_password(Socket, Password) of ok -> ok; _Err -> error_logger:error_msg("Auth error") end; _Err -> error_logger:error_msg("Unknown user") end; Err -> error_logger:error_msg("Could not receive_greetings") end; _Error -> error_logger:error_msg("Could not connect") end.
Wow. Now we have added all of the error code. And wow, the size of the code has increased by 400%⊠with a commensurate decrease in readability. Ouch!
Perhaps there is a cleaner way to implement this?
Designing for better errors handling with âthe railwayâ approach (theory)
The idea behind the railway approach is to decompose âstepâ functional blocks, using railway switches as an analogue:
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.