Судя по тексту вопроса, вы мыслите категориями императивного стиля и объектно-ориентированной парадигмы, где переменная - это коробка, в которой лежат данные, а код - это последовательность конкретных действий, типа "возьми данные из коробки, прибавь к ним единицу, положи обратно в коробку". В ФП нет состояния/коробки. В ФП данные трактуются как последовательность их преобразований.
Например есть некоторая функция складывающая аргументы:
function addition(a, b) {
return a + b;
}
И есть некое значение-аккумулятор
X
. Значение
X
не равно 7, значение
X
равно
addition(addition(addition(addition(addition(addition(1, 1), 1), 1), 1), 1), 1)
или
addition(addition(addition(1, 2), 3), 1)
или сотням других вариантов. То есть
функции от предыдущих состояний, в математическом смысле.
Естественно, в реальном мире не всё так радужно, как в теории. Совсем без
состояния обойтись нельзя, и на низком уровне оно всё равно хранится как некоторое значение области памяти. Но функциональщику не приходится заморачиваться мелочами вроде порядка выполнения, синхронизацией и т.п. Он просто описывает высокоуровневые правила преобразований, а обо всём остальном беспокоится среда выполнения.
Например в Clojure один из способов решить задачу подобную описанной вами - использовать
атом.
;; Создаём счётчик с нулевым начальным значением
(def counter (atom 0))
;; Применяем к нему функцию инкремента
(swap! counter inc)
Любую функцию, в том чилсе более сложную, чем инкремент, можно применить к
атому,
транзакционной памяти или
агенту в нагруженной многопоточной среде и даже не задумываться о возникновении
гонки, взаимоблокировки и прочем.
Если развить задачу до работы с персистентными данными в базе, то для clojure-программиста сложнее она не станет. Достаточно использовать СУБД
Datomic, построенную на идее event sourcing'а, при которой в БД хранятся не сами значения, а последовательность операций над ними. Эффект тот же, что и с атомом - сто клиентов одновременно зафиксировали в БД намерение увеличить
counter
, а сто первый получил результат применения ста инкрементов к начальному значению.