lt1*_*lt1 5 functional-programming memoization immutability elixir
我主要是从Java语言背景来学习Elixir的。在JS中,可以编写一个更高阶的函数“一次”,该函数返回一个仅调用传入函数一次的函数,并在后续调用中返回前一个结果-技巧是处理通过闭包捕获的变量:
var once = (func) => {
var wasCalled = false, prevResult;
return (...args) => {
if (wasCalled) return prevResult;
wasCalled = true;
return prevResult = func(...args);
}
}
Run Code Online (Sandbox Code Playgroud)
在我看来,由于Elixir不同的变量重新绑定行为,因此无法在Elixir中创建此函数。是否还有其他聪明的方法可以通过模式匹配或递归来实现,或者只是不可能?没有宏,我想那些可以启用它。谢谢
使用当前进程字典:
defmodule A do
def once(f) do
key = make_ref()
fn ->
case Process.get(key) do
{^key, val} -> val
nil ->
val = f.()
Process.put(key, {key, val})
val
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
或者,如果函数将跨进程传递,则ets可以使用表:
# ... during application initialization
:ets.new(:cache, [:set, :public, :named_table])
defmodule A do
def once(f) do
key = make_ref()
fn ->
case :ets.lookup(:cache, key) do
[{^key, val}] -> val
[] ->
val = f.()
:ets.insert(:cache, {key, val})
val
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
Application.put_env/Application.get_env也可用于保存全局状态,但通常用于配置设置。