将 elixir 1.0 应用程序迁移到 1.2 并在模块结构的 derive Collectable 方面出现问题
migrating elixir 1.0 app to 1.2 and having issues with derive Collectable for module struct
1.0 实现如下所示。
defmodule Chat do
use GenServer
@derive [Access, Collectable]
defstruct [api: APIClient, chat_id: nil, clients: %{}]
def start_link(params), do: GenServer.start_link(__MODULE__, params)
def init(params) do
state = Enum.into(params, %__MODULE__{})
{:ok, state}
end
...
end
第一个问题是 Access 已被弃用,这是否意味着我必须在访问状态字段时更改点表示法?
第二个问题是,如果我不删除 @derive Collectable,我会收到此错误 Collectable.Any is not available, cannot derive Collectable ...
。
这里 params
是一个关键字列表,我想我可以将关键字列表转换为 Map
和 state = Map.merge(%__MODULE__{}, Enum.into(params, %{}))
但感觉非常笨拙。
我不确定特定的 Collectable
问题,但是对于您的特定问题有更好的解决方案 - 从 key-value 对列表构建结构。
您可以为此使用 Kernel.struct/2
。它不仅会为您构建结构,还会验证键,并仅使用结构中真正存在的键。从 1.2 开始,如果提供的任何键无效,就会出现 Kernel.struct!/2
。
1.0 实现如下所示。
defmodule Chat do
use GenServer
@derive [Access, Collectable]
defstruct [api: APIClient, chat_id: nil, clients: %{}]
def start_link(params), do: GenServer.start_link(__MODULE__, params)
def init(params) do
state = Enum.into(params, %__MODULE__{})
{:ok, state}
end
...
end
第一个问题是 Access 已被弃用,这是否意味着我必须在访问状态字段时更改点表示法?
第二个问题是,如果我不删除 @derive Collectable,我会收到此错误 Collectable.Any is not available, cannot derive Collectable ...
。
这里 params
是一个关键字列表,我想我可以将关键字列表转换为 Map
和 state = Map.merge(%__MODULE__{}, Enum.into(params, %{}))
但感觉非常笨拙。
我不确定特定的 Collectable
问题,但是对于您的特定问题有更好的解决方案 - 从 key-value 对列表构建结构。
您可以为此使用 Kernel.struct/2
。它不仅会为您构建结构,还会验证键,并仅使用结构中真正存在的键。从 1.2 开始,如果提供的任何键无效,就会出现 Kernel.struct!/2
。