Functional Programming Checklist

Hello all could anyone help me with this:

I wanna create a list of things I can check for in my code, to determine whether I’m properly following the correct functional programming principles, for example, say I have written a function I wanna have a list to check against, that

  1. Is the function pure?
  2. if the function uses recursion, does it use tail optimization?

and I would like to know, what are the things to look out for when determining whether a function, is purely functinal, I hope you get me thankx in advance

1 Like

Hello and welcome,

  1. A function is pure when there are no side effects. Pure function always returns the same output for the same input.

  2. It’s TCO when the last call is a call to the function itself.

BTW Elixir/Erlang are full of side effects, but You can manage this by pushing those impure functions to the outside boundaries, and keep the core pure.

4 Likes

You might algo find this video helpful about Functional Programmingin Elixir: https://youtu.be/Zee4bbsDvrA

1 Like

That is not fully true. Pure function do not change system state after it returns. So for example function like:

def add(a, b) do
  IO.puts("Adding #{a} and #{b}")
  a + b
end

Will always return the same value, but isn’t pure (IO state changes). In Erlang it is particularly hard to have “pure pure functions” as almost everything rely sooner or later on some kind of message passing, and message passing by its nature, in impure.

1 Like

I should have mentionned it also implies no change to system state, no console output, no db call etc :slight_smile:

I believe tail call only mean the last thing to do in a function is a function call, not necessarily to the same function. A tail call does not need stack operation because the called function can just directly return to the previous function in the call chain. ie:

A called B and B called C

If the call from B to C is a tail call, C can return directly to A. The tail call degenerates to a jump.

1 Like

I thought it has to call itself to be TCO…

Maybe some explanation from Erlang can help.

http://erlang.org/pipermail/erlang-questions/2016-October/090663.html

1 Like

If it tail call itself then it becomes a loop, which is as fast as it can be. If it tail call something else then it is still a just a jump, and the stack stays at constant size.

2 Likes

Pure may not be the right metric for a language like Elixir.

Most languages would call a function that returns a random value the current date or time impure, and they are. There are reasons to include such functions in a core. There are other functions that are pure. like ints |> Enum.sum |> Kernel./(Enum.count(elements). That function is pure, but it can fail, so without some tightening, it should not be part oof a core.

So the best advice that I could give you is this: put things in your core that are predictable, and have properties that are easy to test and reason about, in your core. Put things that are unpredictable elsewhere.

So I can’t give you hard and fast heuristics about what’s pure, but I can tell you that generally, I am OK with having things like references, random numbers, and date/time generation from clean inputs in my core. And I limit unchecked user input and functions that are unpredictable in my boundary.

The main difference between core and boundary is the way you compose with functions. Generally, pipes vs withs, but it’s more complicated than that. I know I didn’t answer your question, but I hope it helps.

4 Likes