如何将值缓存在 Elixir 函数中?

How can values be cached in an Elixir function?

一、计数器函数:

在 C++ 中,我可以执行以下操作来缓存跨函数调用的值(无耻地从 TutorialsPoint.com 复制):

void func( void ) {
   static int i = 5; // local static variable
   i++;
   std::cout << "i is " << i ;
   std::cout << " and count is " << count << std::endl;
}

二、数据库缓存示例:

defmodule ElixirTesting do

  def test_static_function_variable do
    IO.puts(get_value_from_db_cache("A"))
    IO.puts(get_value_from_db_cache("B"))
    IO.puts(get_value_from_db_cache("A"))
    true
  end

  defp get_value_from_db_cache(key) do

    # We want this to be static.
    data_cache = %{}

    if !Map.has_key?(data_cache, key) do
      # Scope of this assignment is limited to local if block so does not re-bind static variable.
      data_cache = Map.put_new(data_cache, key, get_value_directly_from_db(key))
    end

    data_cache[key]
  end

  @db_data %{ "A" => 3, "B" => 4, "C" => 5, "D" => 6 }
  defp get_value_directly_from_db(key) do
    IO.puts("Inside get_value_directly_from_db for key #{key}")
    @db_data[key]
  end

end

控制台输出:

Inside get_value_directly_from_db for key A
Inside get_value_directly_from_db for key B
Inside get_value_directly_from_db for key A

对于这两种情况,我怎样才能在 Elixir 中实现相同的效果?或者,我应该如何进行重构以使用适当的功能设计来实现结果?

简短的回答是 - 你不能。函数式意味着您使用纯函数进行编程,因此对于相同的输入它们总是 return 相同的结果,在函数中缓存某些内容会破坏

更长的答案是——当您想管理某些状态时,Elixir 中的默认设置是将该状态包装在一个进程中。一种只保留一段数据的简单类型的进程称为 Agent。例如,您可以启动一个命名代理,并在您的函数中引用它,如下所示:

defmodule Test do
  def start_link(initial_value) do
    Agent.start_link(fn -> initial_value end, name: MyAgent)
  end

  def put(value), do: Agent.update(MyAgent, fn _ -> value end)

  def get, do: Agent.get(MyAgent, fn value -> value end)
end

Test.start_link(:value1)

Test.get() |> IO.inspect() # => :value1
Test.put(:value2)
Test.get() |> IO.inspect() # => :value2