“获取或插入”更惯用的方式是什么?
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)
我有一些代码可以通过在 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)