【问题标题】:How can values be cached in an Elixir function?如何在 Elixir 函数中缓存值?
【发布时间】:2021-09-13 21:33:21
【问题描述】:

一、计数器功能:

在 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 中实现相同的效果?或者,我应该如何进行重构以使用适当的功能设计来完成结果?

【问题讨论】:

    标签: elixir


    【解决方案1】:

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

    更长的答案是 - 当您想要管理某些状态时,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
    

    【讨论】:

    • 考虑使用counters 和/或persistent_term 进行全局缓存。
    • 感谢您的反馈。所以......我担心的是数据库缓存是一个用例,其中 FP 的好处受到现实世界需求的挑战。所以听起来代理为此目的封装了可变数据。浏览文档是有道理的,你是对的。以及有趣的关于这些功能的 Aleksei;它们是否可以从 Elixir 调用,语法是什么?
    • 咳咳。与任何其他 erlang 合格电话一样::module.function(arguments),例如。 G。 :persistent_term.get(:my_term_name).
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多