E
E
Evgeny2018-08-27 11:20:44
Functional programming
Evgeny, 2018-08-27 11:20:44

How to deal with immutable objects in an asynchronous (or multi-threaded) environment?

I study FP, some points are not clear.
In general, I program in NodeJS and React, but I’m interested in FP in a broader sense than just in the JS language, so I’m asking not only about asynchrony, but also about multithreading.
What I understood:
1. Immutability allows you to work safely in an asynchronous / multi-threaded environment, because. everyone always has a fully initialized object, and it will not change in the course of work
2. It is easy to track changes
Actually questions:
Example: two different clients make a request to change the same object at the same time. Let's assume that for change of a resource it is necessary to execute some asynchronous operations. The handlers of each request take an immutable object and each changes it in their own way, since there are asynchronous operations inside, they can process it, in fact, in parallel.
3. Will there be a conflict upon completion of processing?
4. Or you will need to save the intermediate value back to the store from where the object was taken from before performing the asynchronous operation. In this case, this object may contain non-consistent data.
5. Organize a queue and make changes to objects in the store only by sending actions to the queue and then sequentially perform operations from the queue?
Maybe I don't understand something? According to FP, I found only that immutability, higher-order functions and pure functions. But how to work with all this is not clear. While everything is synchronous - everything is beautiful, then the FP is especially not needed.
Maybe something to read?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2018-08-27
@sergey-gornostaev

Judging by the text of the question, you think in terms of the imperative style and the object-oriented paradigm, where a variable is a box that contains data, and code is a sequence of specific actions, such as "take the data from the box, add one to it, put it back in box." There is no state/box in FP. In FP, data is treated as a sequence of their transformations.
For example, there is some function that adds arguments:

function addition(a, b) {
    return a + b;
}

And there is a certain value-accumulator X. Value Xis not 7, value Xis
or addition(addition(addition(1, 2), 3), 1)or hundreds of other options. That is, functions from previous states, in the mathematical sense.
Naturally, in the real world, not everything is as rosy as in theory. You can’t do without state at all, and at a low level it is still stored as some value of a memory area. But the functionalist does not have to bother with trifles like execution order, synchronization, etc. It just describes the high-level transformation rules, and the runtime takes care of the rest.
For example, in Clojure, one way to solve a problem like the one you describe is to use an atom .
;; Создаём счётчик с нулевым начальным значением
(def counter (atom 0))

;; Применяем к нему функцию инкремента
(swap! counter inc)

Any function, even more complex than an increment, can be applied to an atom , transactional memory, or agent in a heavily multithreaded environment and not even think about the occurrence of race conditions , deadlocks, and so on.
If the task is developed to work with persistent data in the database, then it will not become more difficult for a clojure programmer. It is enough to use the Datomic DBMS , built on the idea of ​​event sourcing, in which not the values ​​themselves are stored in the database, but the sequence of operations on them. The effect is the same as with the atom - one hundred clients simultaneously recorded in the database the intention to increase counter, and the one hundred and first received the result of applying one hundred increments to the initial value.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question