visit
When you first start learning about Elixir, you learn that states and side effects are evil, that every function should be “pure”, taking strictly an input and returning strictly an output without mutating anything on the process. Then, you learn this:
IO.puts/1
takes a string and returns an atom :ok
with an obvious big side effect, writing to stdout
. Why is this okay in this case? We don’t know. Why not being strictly functional and having IO.puts
take 2 arguments, a representation of the terminal input/output state and the string we want to print deferring the actual printing when we actually run the program? That will be more functional no matter how impractical it is. But, why not? If functional is useful in other cases, it should be also useful here to work like this. If it’s impractical, how we define what should be purely functional and what should have a more pragmatic approach? The absence of guidelines on this particular topic doesn’t help to understand where to draw the line. I think this absence just shows how clueless we can be about functional programming.
Take Phoenix, an elixir based web framework. They are trying the latter approach. They pass an object conn
to every single functions. To avoid having global states at all costs. conn
contains all request data and all response data. So, you’ll have stuff like this:
Functional programing, object oriented programing, imperative and declarative programing, are all interesting by themselves and bring to the table well-thought concepts that make us better programmers. Here the big secret. Good programers will produce good code anyway. Bad programers will produce unreadable code anyway. Trying to make bad programmers better by imposing to everyone some magic programming paradigm is a mirage. It never worked and is the biggest lie in our industry.