Procedural programming – specifies the steps a program must take to reach a desired state. Functional programming – treats programs as evaluating mathematical functions and avoids state and mutable data.
The major difference between Procedural and Object-oriented programming is that POP follows a top-down approach whereas OOPs follow a bottom-up approach. Procedural oriented programming is also known as POP and Object-oriented programming is known as OOP.
Imperative programming refers to code that is concerned with lower levels of abstraction. Procedural programming is a subset of imperative programming which utilizes subroutines. Functional programming is a subset of declarative programming which utilizes subroutines.
In procedural programming, we work with procedures, also known as routines, subroutines, or functions. A procedure is essentially a sequence of instructions or computational steps to be executed. Therefore, procedural programming is all about the idea of getting things done in a sequence of steps.
Functional Programming
Functional programming refers to the ability to treat functions as values.
Let's consider an analogy with "regular" values. We can take two integer values and combine them using the +
operator to obtain a new integer. Or we can multiply an integer by a floating point number to get a floating point number.
In functional programming, we can combine two function values to produce a new function value using operators like compose or lift. Or we can combine a function value and a data value to produce a new data value using operators like map or fold.
Note that many languages have functional programming capabilities -- even languages that are not usually thought of as functional languages. Even Grandfather FORTRAN supported function values, although it did not offer much in the way of function-combining operators. For a language to be called "functional", it needs to embrace functional programming capabilities in a big way.
Procedural Programming
Procedural programming refers to the ability to encapsulate a common sequence of instructions into a procedure so that those instructions can be invoked from many places without resorting to copy-and-paste. As procedures were a very early development in programming, the capability is almost invariably linked with the style of programming demanded by machine- or assembly-language programming: a style that emphasizes the notion of storage locations and instructions that move data between those locations.
Contrast
The two styles are not really opposites -- they are just different from one another. There are languages that fully embrace both styles (LISP, for example). The following scenario may give a sense of some differences in the two styles. Let's write some code for a nonsense requirement where we want to determine if all of the words in a list have an odd number of characters. First, procedural style:
function allOdd(words) {
var result = true;
for (var i = 0; i < length(words); ++i) {
var len = length(words[i]);
if (!odd(len)) {
result = false;
break;
}
}
return result;
}
I'll take it as a given that this example is comprehensible. Now, functional style:
function allOdd(words) {
return apply(and, map(compose(odd, length), words));
}
Working from the inside out, this definition does the following things:
compose(odd, length)
combines the odd
and length
functions to produce a new function that determines whether the length of a string is odd.map(..., words)
calls that new function for each element in words
, ultimately returning a new list of boolean values, each indicating whether the corresponding word has an odd number of characters.apply(and, ...)
applies the "and" operator to the resulting list, and-ing all of the booleans together to yield the final result.You can see from these examples that procedural programming is very concerned with moving values around in variables and explicitly describing the operations needed to produce the final result. In contrast, the functional style emphasizes the combination of functions required to transform the initial input to the final output.
The example also shows the typical relative sizes of procedural versus functional code. Furthermore, it demonstrates that the performance characteristics of procedural code might be easier to see than that of functional code. Consider: do the functions compute the lengths of all of the words in the list, or does each stop immediately after finding the first even length word? On the other hand, the functional code permits a high-quality implementation to perform some pretty serious optimization since it primarily expresses intent rather than an explicit algorithm.
Further Reading
This question comes up a lot... see, for example:
John Backus' Turing award lecture spells out the motivations for functional programming in great detail:
Can Programming Be Liberated from the von Neumann Style?
I really shouldn't mention that paper in the present context because it gets pretty technical, pretty quickly. I just couldn't resist because I think it is truly foundational.
Addendum - 2013
Commentators point out that popular contemporary languages offer other styles of programming over and above procedural and functional. Such languages often offer one or more of the following programming styles:
See the comments below for examples of how the pseudo-code examples in this response can benefit from some of the facilities available from those other styles. In particular, the procedural example will benefit from the application of virtually any higher-level construct.
The exhibited examples deliberately avoid mixing in these other programming styles in order to emphasize the distinction between the two styles under discussion.
The real difference between functional and imperative programming is the mindset - imperative programmers are thinking of variables and blocks of memory, whereas functional programmers are thinking, "How can I transform my input data into my output data" - your "program" is the pipeline and set of transforms on the data to take it from the Input to the Output. That's the interesting part IMO, not the "Thou shalt not use variables" bit.
As a consequence of this mindset, FP programs typically describe what will happen, instead of the specific mechanism of how it will happen - this is powerful because if we can clearly state what "Select" and "Where" and "Aggregate" means, we are free to swap out their implementations, just like we do with AsParallel() and suddenly our single-threaded app scales out to n cores.
Isn't that the same exact case for procedural programming?
No, because procedural code can have side-effects. For example, it can store state between calls.
That said, it is possible to write code that satisfies this constraint in languages considered procedural. And it is also possible to write code that breaks this constraint in some languages considered functional.
I disagree with WReach's answer. Let's deconstruct his answer a bit to see where the disagreement comes from.
First, his code:
function allOdd(words) {
var result = true;
for (var i = 0; i < length(words); ++i) {
var len = length(words[i]);
if (!odd(len)) {
result = false;
break;
}
}
return result;
}
and
function allOdd(words) {
return apply(and, map(compose(odd, length), words));
}
The first thing to note is that he is conflating:
programming, and missing the ability for iterative style programming to have more explicit control flow than a typical functional style.
Let's quickly talk about these.
Expression-centric style is one where things, as much as possible, evaluate to things. Although functional languages are famed for their love of expressions, it's actually possible to have a functional language without composable expressions. I'm going to make one up, where there are no expressions, merely statements.
lengths: map words length
each_odd: map lengths odd
all_odd: reduce each_odd and
This is pretty much the same as given before, except functions are chained purely through chains of statements and bindings.
An iterator centric programming style might be one taken by Python. Let's use a purely iterative, iterator-centric style:
def all_odd(words):
lengths = (len(word) for word in words)
each_odd = (odd(length) for length in lengths)
return all(each_odd)
This is not functional, because each clause is an iterative process, and they are bound together by explicit pause and resumption of the stack frames. The syntax may be inspired partially from a functional language, but it is applied to a completely iterative embodiment of it.
Of course, you can compress this:
def all_odd(words):
return all(odd(len(word)) for word in words)
Imperative doesn't look so bad now, eh? :)
The final point was about more explicit control flow. Let's rewrite the original code to make use of this:
function allOdd(words) {
for (var i = 0; i < length(words); ++i) {
if (!odd(length(words[i]))) {
return false;
}
}
return true;
}
Using iterators you can have:
function allOdd(words) {
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
}
So what is the point of a functional language if the difference is between:
return all(odd(len(word)) for word in words)
return apply(and, map(compose(odd, length), words))
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
The main definitive feature of a functional programming language is that it removes mutation as part of the typical programming model. People often take this to mean that a functional programming language does not have statements or uses expressions, but these are simplifications. A functional language replaces explicit computation with a declaration of behaviour, which the language then performs a reduction on.
Restricting yourself to this subset of functionality allows you to have more guarantees about your programs' behaviours, and this allows you to compose them more freely.
When you have a functional language, making new functions is generally as simple as composing closely-related functions.
all = partial(apply, and)
This is not simple, or perhaps even not possible, if you haven't explicitly controlled global dependencies of a function. The best feature of functional programming is that you can consistently create more generic abstractions and trust that they can be combined into a greater whole.
In procedural paradigm (shall I say "structured programming" instead?), you have shared mutable memory and instructions which read/write it in some sequence (one after the other).
In functional paradigm, you have variables and functions (in the mathematical sense: variables do not vary over time, functions can only compute something based on their inputs).
(This is oversimplified, e.g., FPLs typically have facilities for working with mutable memory whereas procedural languages can often support higher-order procedures so things are not as clear-cut; but this should give you an idea)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With