Register to get access to free programming courses with interactive exercises

Programming paradigms JS: Functions

We often use the term "paradigm" in programming.

A programming paradigm is a set of ideas and concepts that define the style, or programming approach, for writing computer programs. It's a way of conceptualizing, that defines the organization of computation and structures the work done by a computer.

A paradigm is more than just another problem-solving algorithm. Generally, the code structure differs greatly when using different paradigms and requires knowledge beyond just language syntax (for example, automata-based programming requires at least a basic understanding of automata theory). And the vast majority of modern (and not so modern) programming languages are multi-paradigm, allowing you to write code using many styles. Sometimes, these styles are mutually exclusive, but sometimes they complement each other. As of now, we've written code using two paradigms, imperative and declarative.

Paradigms

The Imperative Paradigm

The imperative paradigm is a style of writing code as a set of sequential instructions (commands) with active use of variables. This definition may seem scary, but in practice, the imperative style is the dominant one. Excluding this course, all the rest of our code has been written in the imperative style.

// Search for the maximum number
const numbers = [10, 20, 52, 105, 56, 89, 96];

let max = numbers[0];
for (const number of numbers) {
  if (number > max) {
    max = number;
  }
}

console.log(max); // => 105

The imperative style makes extensive use of assignment (and therefore variables) and loops. This paradigm is popular because it corresponds exactly to how a computer works: it sequentially executes instructions and uses memory to store intermediate results. An imperative program is often said to answer HOW questions(“how to achieve the desired result”).

JavaScript, like Java, Ruby, Python, C#, Perl, PHP, and Go, is an imperative language. I.e., it's' a language in which the imperative paradigm is dominant (the language pushes you to use it). This, however, does not prevent the use of other paradigms within these languages.

The Declarative Paradigm

The declarative style is often referred to as the functional style, it's very much the opposite of the imperative style. The key difference between the functional and the imperative style is that with this style, the program looks like a datasheet (which can be very complex) rather than a set of instructions. That is, the program answers WHAT questions ("what we want to get"). This is rather difficult to grasp straight away, but we can look at it this way: mathematics is inherently declarative.

// Find the maximum number
const numbers = [10, 20, 52, 105, 56, 89, 96];

const max = numbers.reduce(
  (acc, number) => number > acc ? number : acc,
  numbers[0],
);

console.log(max); // => 105

The main difference between the declarative and the imperative paradigm, in fact, is that you don't assign values to variables in declarative programming. You can argue that the code above defines constants and stores values in them. If you look at the code more closely, you'll notice that constants are created exactly once, are initialized with their original values, and don't change anymore (which is the point of constants). A construct like const myVar = expression, can be viewed as a logical proposition. In mathematics, it would sound like this: “suppose A is a set of numbers”. No matter what we do next, “A” is always the same as it was at the time of the definition.

The fact is that in mathematics, proofs are constructed using chains of logic. Statements follow other statements, and this is how we reach the solution to a given problem. None of this is possible if the statements don't change. Otherwise, the results may be wrong after they've been received, which means we can't reason logically.

The same goes for acc and number. These parameters are always only defined once since each function call in this definition (without reference values) does not depend on other calls. In the world of functional languages, this operation is called binding. Visually it looks like assigning something to a variable, but it's not. Attempting to bind an already bound identifier (there are no variables in functional languages) will result in an error. Below is an example in Erlang:

1> A = 4.
4
2> A = 'hey'.
** exception error: no match of right hand side value hey

Not being able to assign variables means that loops are incompatible with functional programming. Recursion is used instead. Another important feature of the functional style is that functions are actively used as first-class objects. Mostly in higher-order functions. And they can replace recursion for the vast majority of tasks, as we've already seen in previous lessons (where we even omit recursion). Any of the problems presented were solved by the three main higher-order functions.

There are quite a few languages that use the declarative paradigm. They are, on the whole, less popular than imperative ones, but they firmly occupy certain niches and are actively used in programming for certain industries. Such languages include: Haskell/Erlang/Elixir/OCaml/F#. There are no assignments or loops in these languages. It's simply impossible to write imperative code using them. Languages like Scala and Clojure stand out quite a lot (as do others in the LISP family). In these languages, the basic paradigm is declarative, and the language pushes you towards writing in this style, but you can write real imperative code by assigning values to variables and using loops if necessary. But almost all imperative languages allow you to write declaratively. Moreover, while some languages have rather weak support for the declarative paradigm, others are so powerful that you can write in them purely declaratively (if you want to). The latter includes modern JavaScript.

Other Paradigms

Most other paradigms are varieties of the functional or imperative paradigm. The most significant, in my opinion, are the following:

  • Logic programming
  • Automata-based programming
  • Object-oriented programming
  • Metaprogramming

Recommended materials

  1. Programming paradigm
  2. Referential transparency

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.