If my function meets the two requirements listed below, I believe that the function Sum
returns the summation of the items in a list, where item evaluates as true for a given condition. Doesn't this mean that the function can be classified as pure?
Requirements
-
For given set of i/p, the same o/p is returned irrespective of when the function is called
-
It does not have any side effects
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if(predicate(item)) result += item;
return result;
}
Example : Sum(x=>x%2==0, new List<int> {1,2,3,4,5...100});
The reason I ask is that I see , almost everywhere, people advising to avoid the assignment operator and loops because it is characteristic of the imperative programming style.
So, what can go wrong with the above example which makes use of loops and the assignment operator in the context of function programming ?
Best Answer
What is it in functional programming that makes a difference?
Functional programming is by principle declarative. You say what your result is instead of how to compute it.
Let's take a look at really functional implementation of your snippet. In Haskell it would be:
Is it clear what the result is? Quite so, it is sum of the numbers meeting the predicate. How is it computed? I don't care, ask the compiler.
You could possibly say that using
sum
andfilter
is a trick and it doesn't count. Let implement it without these helpers then (though the best way would be to implement them first).The "Functional Programming 101" solution that doesn't use
sum
is with recursion:It is still pretty clear what is the result in terms of single function call. It is either
0
, orrecursive call + h or 0
, depending onpred h
. Still pretty straighforward, even if the end result is not immediately obvious (though with a little bit of practice this really reads just like afor
loop).Compare that to your version:
What is the result? Oh, I see: single
return
statement, no surprises here:return result
.But what is
result
?int result = 0
? Doesn't seem right. You do something later with that0
. Ok, you additem
s to it. And so on.Of course, for most programmers this is pretty obvious what happens in a simple funciton like this, but add some extra
return
statement or so and it suddenly gets harder to track. All the code is about how, and what is left for the reader to figure out - this is clearly a very imperative style.So, are variables and loops wrong?
No.
There are many things that are much easier explained by them, and many algorithms that require mutable state to be fast. But variables are inherently imperative, explaining how instead of what, and giving little prediction of what their value may be a few lines later or after a few loop iterations. Loops generally require state to make sense, and so they are inherently imperative as well.
Variables and loops are simply not functional programming.
Summary
Contemporarily funcitonal programming is a bit more of style and a useful way of thinking than a paradigm. Strong preference for the pure functions is in this mindset, but it's just a small part actually.
Most widespread languages allow you to use some functional constructs. For example in Python you can choose between:
or
or
These functional expressions fit nicely for that kind problems and simply makes code shorter (and shorter is good). You shouldn't thoughtlessly replace imperative code with them, but when they fit, they are almost always a better choice.