“获取或插入”更惯用的方式是什么?

What is a more idiomatic way of “get or insert”?

我有一些代码可以通过在 ETS 中查找用户或创建结构、将该值存储在 ETS 中并返回新创建的用户来评估 user

user = if user = Data.lookup(phone) do
  user
else 
  user = %User{phone: phone}
  Data.insert({phone, user})
  user
end

但是,它对我来说并不是最好的代码,我不确定如何重构它。在 Elixir 中执行此操作的惯用方法是什么?

我肯定会使用模式匹配:

def get_user(phone, nil) do
  user = %User{phone: phone} 
  Data.insert({phone, user})
  user
end
def get_user(phone, %User{} = user), do: user

然后您可以从您的代码中调用:

user = get_user(phone, Data.lookup(phone))

虽然@Daniel 的回答是完全正确的,我很可能会在生产中使用它,但为了多样性,这里有另一种方法。

如果需要,可以在之后实现 Access behaviour on Data, hiding all the implementation details there and use Kernel.get_in/2 以透明地创建用户。


此外,不是 boolean-strict 析取 Kernel.||/2 会做:

defp create_user(phone) do
  user = %User{phone: phone}
  Data.insert({phone, user})
  user 
end

user = Data.lookup(phone) || create_user(phone)