gpt4 book ai didi

types - 结构的透析器错误

转载 作者:行者123 更新时间:2023-12-05 08:56:48 25 4
gpt4 key购买 nike

这是 Elixir 1.3 中的一个最小错误示例:

defmodule Foo do
@type t :: %__MODULE__{x: non_neg_integer}
defstruct x: 0

@spec test(t) :: t
def test(%__MODULE__{} = foo), do: test2(foo)

@spec test2(t) :: t
defp test2(%__MODULE__{} = foo), do: %__MODULE__{foo | x: 5}

end

这无法通过以下方式进行类型检查:foo.ex:9: 变量 _@1 永远无法匹配,因为前面的子句完全覆盖了类型 #{'__struct__':='Elixir.Foo', _=> _}.

我搜索了又搜索,终究找不到这意味着什么或如何修复它的解释。

最佳答案

如果将代码简化为:

defmodule Foo do
@type t :: %__MODULE__{x: non_neg_integer}
defstruct x: 0

@spec set_x_to_5(t) :: t
def set_x_to_5(%__MODULE__{} = foo), do: %__MODULE__{foo | x: 5}
end

然后反编译生成的 .beam 文件,你会得到:

set_x_to_5(#{'__struct__' := 'Elixir.Foo'} = foo@1) ->
case foo@1 of
_@1 = #{'__struct__' := 'Elixir.Foo'} -> _@1#{x := 5};
_@1 -> erlang:error({badstruct, 'Elixir.Foo', _@1})
end.

如果你看到 Elixir 为 %__MODULE__{foo | 生成的 case 语句x: 5} 仔细看,您会发现它包含一个永远无法匹配的分支,因为 __struct__ 在该函数内保证为 Foo。这是由 Elixir 生成的,因为如果您使用 %Struct{map | Elixir 会抛出错误...} 具有不同结构的 map 的语法:

iex(1)> defmodule Foo, do: defstruct [:x]
iex(2)> defmodule Bar, do: defstruct [:x]
iex(3)> %Foo{%Bar{x: 1} | x: 2}
** (BadStructError) expected a struct named Foo, got: %Bar{x: 1}

要解决此问题,您可以删除 __MODULE__ 部分并执行以下操作:

%{foo | x: 5}

结果是一样的,你不会收到任何警告。

关于types - 结构的透析器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38800459/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com