📜 ⬆️ ⬇️

Pure functions

Pure functions have a number of interesting and useful properties. It's simple. They depend only on their parameters. And return only their result. In the D programming language, the following are possible:

The following is an example of a pure D function:

pure int foo(int x, const int[] a)
{
int sum = 0;
foreach (s; a)
sum += s; //
return x * sum;
}


And not a pure function:

int bar(int x, int[] a)
{ static int sum = 0;
foreach (s; a) //
sum += s; // /
return x * sum; //
}


If the pure keyword is specified, the properties of such a pure function are checked at compile time. The main question is, if the compiler can check the function for purity, then why annotate it accordingly? Why not transfer to the compiler's shoulders the annotation of a clean function, if it sees that this is the case? The bottom line is that it was the programmer who knew that this function did not forget. Otherwise it is possible that he will not be able to say exactly what the function is. And write, depending on this, the appropriate code.
')
Fine. We have pure features. What is so good about it?

First of all, it is self-documentation. The person reading the code will immediately realize that the function depends only on its parameters, has no side effects and nothing strange happens in it if it is marked clean. This greatly reduces the amount of unnecessary work. Most of the features can be marked clean. And it is this that has a positive effect on the support of the code.

Pure functions do not need synchronization when using multiple threads. Because all their variables are either local or immutable.

Below is a good example describing possible code optimizations using the pure function by the compiler:

int x = foo(3) + bar[foo(3)];

only one function call foo is required.

Thus, a pure function depends only on the bits passed to it on the stack. And these bits can act as a key to getting data from the cache. Therefore, it is not necessary to call the function again.

Pure functions can be performed asynchronously. This means that not just the code will be executed further, without waiting for the function to be executed. Well, as well as the fact that the execution of the function may be performed on a different processor core. What becomes especially relevant in our days, when no one will be surprised with n-core processors. And such a scheme of work can not but have a positive effect on the program's performance.

They can be swapped during operation, because they do not depend on any global initialization or completion state.

Exactly that the functionality of the program is an interesting addition to the imperative programming languages.

Translated by Andreyenko Artem. Author Walter Bright (co-author of D). The original version of the article.

Source: https://habr.com/ru/post/40697/


All Articles