Как использовать кешированные данные на функциональном языке, таком как Erlang?

В последнее время я немного читал о функциональных языках. Начиная с 10 лет развития OO, мне трудно понять, как на земле можно указать чистый функциональный подход (т.е. Тот же метод, называемый с теми же параметрами, делает то же самое) при проблеме, где обычно (в программе OO) мне нужно будет кэшировать данные.

  • Допустим ли мы, что в программе может быть актер, который не является неизменным (т.е. кеш). Я просто смотрел презентацию Джо Армстронга на infoq, и он казался довольно догматичным в этом отношении!

  • Допустим ли мы, что поиск данных может быть дорогостоящим (потому что мы никогда не можем его кэшировать)? Если да, то каким образом мы можем управлять, например, загрузкой какого-либо общего ресурса (например, базы данных).

  • Есть ли какая-то волшебная фея, о которой я еще не знаю, которая решает всю проблему, а затем делает приятную чашку чая.

Конечно, поиск Google для "Erlang Cache", кажется, возвращает справедливые результаты...

Ответы

Ответ 1

Это данные, которые должны быть неизменными в Эрланге, а не в актерах.

Долгоживущие актеры обычно живут в хвостовой рекурсивной функции, аргументы которой служат их состоянием и, безусловно, могут меняться между вызовами.

-module(cache).
-export([start/0, get_c/1, put_c/2, clear/1]).

start() -> register(spawn(fun () -> loop(dict:new()) end), cache).

loop(Dict) -> receive
                {get, From, Key} -> From ! {cache_result, Key, dict:fetch(Key, Dict)};
                {set, Key, Value} -> NewDict = dict:store(Key, Value, Dict),
                                     loop(NewDict);
                %% etc.
              end

put_c(Key, Value) -> cache ! {set, Key, Value}
%% etc.

Когда вы вызываете put_c, состояние "актер" изменяется, хотя все задействованные данные неизменяемы.

Ответ 2

Запомните функцию. Кэш - это просто список/словарь и, следовательно, может быть реализован исключительно функционально.

Ответ 3

Нет причин, чтобы кэш и функциональный язык не могли жить вместе. Чтобы быть функциональным, вам просто нужно подчиниться ограничению, вызывающему одну и ту же функцию с теми же аргументами, что и тот же ответ.

Например: get_data (Query, CacheCriteria)

Просто потому, что get_data использует кеш, это не значит, что он не работает. Пока вызывается get_data с тем же Query, а аргументы CacheCriteria всегда возвращают одно и то же значение, тогда язык можно считать функциональным.