DEV Community

Shirley
Shirley

Posted on

Functional programming and pure functions

I have had interviewers ask me what functional programming is. I have heard of the term but never known what it really was until recently.

Functional programming is characterized by pure, higher order functions and immutable data. It is a programming paradigm, meaning it is a way of thinking of software construction based on higher level principles. Imperative programming is focused on creating statements that instruct your program every step it needs to take or how to do something whereas declarative programming tells the program what to do.

Pure functions are functions that, given the same input, produces the same output and does not have observable side effects. They are predictable, independent (do not use values in surrounding environment), easy to reuse, simplify state management, and are easy to test.

The map method is a pure function.

A side effect manipulates the state of the program or has observable effects on the program. These include reassigning a new value to a variable, mutating an object. A function has side effects if it changes the external state.

This is an example of a side effect in a function:

let _id = 1
function uniqueId() {
id++;
}
Enter fullscreen mode Exit fullscreen mode

Higher order functions are functions that return a function. First class functions are functions that are treated like a value and can be returned from a function, passed as an argument to a function, assigned as a variable method or stored in an array.

Top comments (13)

Collapse
 
pentacular profile image
pentacular

Well, the map method performs a series of operations in a particular order over time.

So it's not a pure function -- but with discipline it can be a procedure that implements a pure function.

However, there's no requirement that it does -- consider the following.

let n = 0;
const sums = [1, 2, 3].map(a => n += a);
console.log(n);
console.log(sums);
Enter fullscreen mode Exit fullscreen mode

Which demonstrates its procedural nature clearly.

Collapse
 
rsa profile image
Ranieri Althoff

map is as pure as the function you pass as an argument, what you have there is just a very poor usage of what should be reduce.

Also note comment from Iven below about how pure functions interact with the scope it is closed over.

Collapse
 
pentacular profile image
pentacular • Edited

It might be, if map were not specified to perform a series of operations in a particular order.

This makes map in javascript resolutely procedural -- it's not a time invariant relationship.

But sure -- with discipline you can avoid making any of this procedural behavior visible to the user.

Iven's comment does not seem relevant to this.

Thread Thread
 
macsikora profile image
Pragmatic Maciej

You have no access to map and what it does (until you change the Array prototype). What you are showing is that you have passed procedure as predicate to the map function - .map(procedure). It means that you didn't change the map, and map doesn't make any side effects, the procedure makes them. In language with allowed mutation it is natural that you can do that whenever you want, but it doesn't change that map is pure function.

Thread Thread
 
pentacular profile image
pentacular

I know what map is specified to -- it's in the language specification.

callbackfn should be a function that accepts three arguments. mapmap calls callbackfn once for each element in the array, in ascending order, and constructs a new Array from the results. callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

So we know that map is a procedure that executes a series of operations in a particular order over time.

[...]

mapmap does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.

And we know that map must be composed with another procedure to be called.

Which means that it's not meaningful to talk about map by itself, you need to talk about how it may be paramterized.

So, the best that you can say is that map can be a procedure which implements a pure function providing you pass it a procedure implementing a pure function for it to call.

But outside of this special case, it's just another procedure.

Thread Thread
 
macsikora profile image
Pragmatic Maciej

Yes map is a procedure but it is a procedure which doesn't make any side effects, and such procedure is a function. Saying that map is impure because you can pass to it statefull procedure is the same as saying every higher order function is impure as you can pass to if smth impure. That is not true - your call of map is impure because you pass to it smth impure, but map itself is a pure function.

Thread Thread
 
pentacular profile image
pentacular

A procedure is never a function, but it can implement a function - we call this an algorithm.

If map were a pure function you would not be able to compose it with a procedure in the first place.

Thread Thread
 
macsikora profile image
Pragmatic Maciej

If function is not a part of language then we can only make it from procedure by making it referencial transparent. If procedure is referencially transparent then it can be called a function. If not then we cannot name anything a function outside of pure FP languages. But this is more about naming, I have no problem to name everything a procedure as it would be at least better than naming everything a function , what is in a most false in imperative languages.

The thing is that map usage is referencially transparent if we pass to it another referencially transparent function. If we don't the composition is a procedure as you have stated, but IMO if function itself doesn't make side effects we can name it a function, it is fully ok and should not be confusing. As I stated before your opinion makes every HOF not pure even though it's implementation has nothing impure.

Thread Thread
 
pentacular profile image
pentacular

A procedure can never be called a function.

However, as I've said, you can use a procedure as a way to implement a function.

It's important to understand that it's still a procedure, and it's still executing a series of operations over time, as opposed to being a time-invariant relationship.

HOP (higher order procedures) can implement functions, while not being functions -- but the distinction remains.

I don't think we're particularly disagreeing, except on your use of "is" vs "implements".

Thread Thread
 
macsikora profile image
Pragmatic Maciej

Ok, yes I think your way of stating that is correct. Function can be implement by procedure. And .map can be co considered as HOF implementation if we use another transparently referencial procedure as an argument.

Collapse
 
iquardt profile image
Iven Marquardt • Edited

independent (do not use values in surrounding environment)

Not exactly. A pure function may be also a closure and read from free variables of the parent scope it is closed over.

Please note that FP also means programming with values, because side effects and other computational effects are encoded as values.

Another perspective is that FP is about local and equational reasoning. Saying that FP is about purity and higher order functions is okay as well but it is a rather technical perspective.

Collapse
 
macsikora profile image
Pragmatic Maciej

Yes, that is why for example global values are fully ok in FP as they don't change in time. Also encapsulation by closures is still FP until we don't mutate, when we start mutation of what we have closed in a closure we change paradigm into OOP, as object can be considered as closure with private state and exposed behavior.

Collapse
 
samrocksc profile image
Sam Clark

great quick reference article!