如何将值缓存在 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
一、计数器函数:
在 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