Im trying to check with a case if a list is empty rather then recursivly catching the pattern when it is, is this the right way to go in Erlang or am i just walking down the wrong path and pattern matching is the best way to catch if a list has been emptied or not?
calculate([Head|Tail], pi, x, y) ->
...calculations of Head being sent to a list...
case Tail == [] of
false ->
calculate(Tail, pi, x, y)
end.
or should i just pattern match on calculate if the list is empty?
add a clause with empty list, and if not possible, one with a single element list:
Note that this will fail with an empty input list.
Look also if you can use one of the functions lists:map/2 or lists:foldl/3 or list comprehension...
Pattern match. Its the Right Thing.
It is also more efficient. It also prevents you from developing a habit of just accepting any sort of variables up front, going partway through your function and discovering that what you've received isn't even a list (oops!). Pattern matching (and using certain types of guards) are also central to the way Dialyzer checks success typings -- which may or not matter to you right now, but certainly will once you start working on the sort of software that has customers.
Most importantly, though, learning to take advantage of pattern matching teaches you to write smaller functions. Writing a huge function with a bajillion parameters that can do everything is certainly possible, and even common in many other languages, but pattern matching will illustrate to you why this is a bad idea as soon as you start writing your match cases. That will help you in ways I can't even begin to describe; it will seep into how you think about programs without you appreciating it at first; it will cut the clutter out of your nested conditions (because they won't exist); it will teach you to stop writing argument error checking code everywhere.
Error in your code
General practice is to use function clause with pattern match. It works just as case, and it is considered to much more readable. And it fixes one error you have in your implementation:
First of all your code could be rewritten in this manner.
As you can see, one of clauses do not return anything, which is not allowed in Erlang (fail during compilation). Your implementation does exactly same thing.
case
just like anything in Erlang must return some value (and since it is lase statement in your function this value will be returned from function). And sincecase
needs to return something, it needs to match on one of it's clauses. It most cases, sinceTail == []
will returnfalse
it will not be a problem. But at last recursive call, whenTail
is empty list,Tail == []
will returntrue
andcase
will not match to anything. And in Erlang this will cause (throw, or exit to be exact)case_clause
error. So your implementation will always fail.To fix it you need to make sure you always have something matching in you case, like this
Or it could be written like this
where
_
will match to anything, and will work somewhat likeelse
is some other languages. And finally it could be written with function clauses, just like I showed before, but with this sane value returned.EDIT
returning a value
If you look closer at our code wright now we are returning only one value; the one from last recursive call (the one I called "sane"). If you would like to take under account all calculations from all recursive calls you need to accumulate them somehow. And to do this we will use
Acc
variableIn each recursive call we add our calculations
Res
to accumulatorAcc
, and send this updated list to next level of recursion. And finally, when our input list is empty (we processed all data) we just return whole accumulator. All we need to do, is make sure, that whencalculate
is being first called, it is called with empty list asAcc
. This could be done by new (somewhat old) functionNow we can export
calculate/4
and keepcalculate/5
private.