Register to get access to 15+ free programming courses with interactive exercises

Pure functions JS: Functions

Functions in programming have a number of important characteristics. Knowing them enables us to determine more accurately how best to break code into functions and when we actually need to define them.

Determinacy

The built-in JavaScript Math.random() function returns a random number between 0 and 1:

Math.random(); // 0.9337432365797949
Math.random(); // 0.5550694016887598

The function is necessary and useful, but inconvenient in debugging and testing. This is because it can return different values for the same input (including missing arguments). Functions like this are called nondeterministic.

For example, functions that operate with system time are nondeterministic. For example, the Date.now() function returns a new value each time:

// Returns current time in milliseconds
Date.now(); // 1571909874844
Date.now(); // 1571909876648

Here's an example with an input. Imagine a getAge(), function that takes as input the year of birth and returns the age:

getAge(2000); // ?

Though running a function again right now will return the same value, a year from now it will be different. That is, a function is considered nondeterministic if it behaves that way at least once.

Deterministic functions, on the other hand, behave predictably. They always give the same result for the same input. These are the functions in mathematics.

It is interesting that, for example, the console.log() — function is deterministic. The point is that it always returns the same value for any input data. This is the undefined value, not what is printed on the screen, as one might think. Printing is a side effect, we'll talk about it a little later.

console.log('Hexlet – Big Bang');

Calling console.log('Hexlet - Big Bang') performed two actions:

  • Output the Hexlet - Big Bang message to the terminal (or browser console, depending on the runtime)
  • Returned the undefined value. Whatever message we print, the return value will always be undefined.

A function also becomes nondeterministic if it accesses not only its arguments but also external data, such as global variables, environment variables, and so on. This is because the external data can change and the function will produce a different result, even if the same arguments are passed to it.

const getCurrentShell = () => process.env.SHELL;

getCurrentShell(); // /bin/bash

The getCurrentShell() function accesses the SHELL environment variable. But at different times and in different environments, the value of this variable may be different.

Generally speaking, we cannot say that no determinacy is an absolute evil. Many programs and websites require a function that returns a random number or calculates the current date. On the other hand, it is in our power to divide the code so that it has as many deterministic parts as possible. A general recommendation when dealing with determinacy is to write a deterministic function if nothing is in your way. Don't use global variables, create functions that depend only on their own arguments.

The concept of Determinacy is not limited to programming or mathematics. Almost any process can be viewed through it. For example, flipping a coin is a nondeterministic process; the result is random.

Side effects

The second key feature of the functions is the presence of side effects. Side effects are any interactions with the external environment. These include file operations such as writing to a file, reading a file, sending or receiving data over the network, and even output to the console.

const someFunction = () => {
  // The function fetch performs an HTTP request
  // HTTP request is a side effect
  fetch('https://hexlet.io/courses');
};

In addition, changes to external variables (e.g., global ones) and inputs when they are passed by reference are considered side effects.

const someFunction = (obj) => {
  // Some kind of logic
  // Side effect. Changing the input argument.
  obj.key = 'value';
};

Computation (logic), on the other hand, has no side effects. For example, a function that sums up two numbers given as arguments.

const sum = (num1, num2) => num1 + num2;

Side effects are one of the biggest challenges in development. Their presence makes code logic and testing much more difficult. Leads to a huge number of errors. When working with files alone, the number of possible errors is measured in hundreds: from running out of disk space to trying to read data from a non-existent file. To keep code from such errors requires a large number of checks and protection mechanisms.

It is impossible to write any useful program without side effects. Whatever important calculations she does, their result must somehow be demonstrated. In the simplest case, you have to display it on the screen, which automatically leads us to side effects:

console.log(sum(4, 11)); // => 15

In real-world applications, however, it usually comes down to interacting with the database or sending queries over the network.

There is no way to get rid of side effects altogether, but their effect on the program can be minimized. Generally, there aren't many side effects in a common program relative to the rest of the code, and they occur only at the beginning and at the end. For example, a program that converts a file from text format to PDF ideally performs exactly two side effects:

  1. Reads the file at the beginning of the program.
  2. Writes the result of the program to a new file.

Between these two points is the main work, which contains the pure algorithmic part. The side effects will then only reside in the top layer of the application, and the core part that does the main work will remain pure.

Increment and decrement are the only basic arithmetic operations in JS that have side effects (they change the variable value itself). This is why they are difficult to work with in compound expressions. They can lead to errors so hard to catch that many languages have refused to introduce them at all (Ruby and Python have none).

Net functions

Net functions in JavaScript

An ideal function in terms of convenience is called pure. A pure function is a deterministic function that produces no side effects. Such a function depends only on its input arguments and always behaves predictably.

Pure functions have a number of key advantages:

  • It's easy to test them. It is enough to pass the required parameters to the input of the function and see the expected output.
  • They are safe to re-run, which is especially relevant in asynchronous code or in the case of multithreaded code.
  • They are easy to combine to get new behavior without having to rewrite the program (more on that later in the course).

Well-designed programs try to isolate side effects in a small part of the application so that most of the code remains pure.

Right now, this may sound rather abstract. Understanding this topic requires more than just comprehending the words before you but also a knack for the complexity of working through a mishmash of side effects. We will raise the topic of cleanliness on a regular basis. It's especially hard to work out in projects, on live code.


Recommended materials

  1. Side effect
  2. Deterministic algorithm

Аватары экспертов Хекслета

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

The Hexlet support team or other students will answer you.

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

From zero to a developer. Refunds in case you won't get a job

Frontend Developer icon
Profession
New
Development of front-end components for web applications
start anytime 10 months

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.