【问题标题】:Elixir - Why are type specs required in a @callback definition?Elixir - 为什么@callback 定义中需要类型规范?
【发布时间】:2018-07-31 15:24:55
【问题描述】:

似乎当您定义一个行为时,您必须在 @callback 定义中包含类型规范。然后,当您采用该行为时,编译器要求定义 function_name/arity,但如果您不遵循类型规范,则非常高兴。

我的问题是:

  1. 这些观察结果正确吗?
  2. 如果是,为什么@callback 将类型规范与检查function_name/arity 是否已定义的实际功能结合起来?很难理解什么是文档,什么是核心功能。 Elixir 的其余部分似乎清楚地将两者分开,将类型规范作为可选添加。

例如:

如果我们省略类型规范,我们会得到一个编译错误

defmodule Greeting do
  @callback hello(person)
end
# (CompileError) iex:82: type specification missing return type: hello(person)

为了让编译器满意,我们必须包含类型规范:

defmodule Greeting do
  @callback hello(%Person{}) :: {:ok, String.t} | {:error, String.t}
end

现在,当我们采用该行为时,编译器会检查 function_name/arity 是否已定义:

defmodule WesternGreeting do
  @behaviour Greeting
  def hello(), do: "Howdy"
end
# warning: undefined behaviour function hello/1 (for behaviour Greeting)

但是,@callback 中的所有类型规范都被编译器忽略了:

defmodule WesternGreeting2 do
  @behaviour Greeting
  def hello([a, b, c]), do: a <> b <> c
end
# No warnings or errors

【问题讨论】:

  • 规格不是由编译器检查,而是由透析器等外部工具检查
  • @Grych 帖子中的错误是# (CompileError) iex:82: type specification missing return type: hello(person) 这似乎表明编译器确实检查了它。我错过了什么吗?

标签: types module elixir behavior


【解决方案1】:

这是因为@callback@spec 相同,它需要类型。 如果您将在第一个示例中定义返回类型,它也会失败:

iex(1)> defmodule Greeting do
...(1)>   @callback hello(person) :: any()
...(1)> end
** (CompileError) iex:2: type person() undefined

关于检查类型,我想还没有完成

【讨论】:

    【解决方案2】:

    在旧版本的 erlang 中,它不是必需的。沿着这条线的某个地方(我不记得确切的时间),人们意识到如果你添加它们,那么 Dialyzer 可以做一些额外的验证。

    此外,您实际上可以在运行时从具有某些用途的模块中获取类型。

    https://www.youtube.com/watch?v=7lT4_E6dooQ

    【讨论】:

      猜你喜欢
      • 2018-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 2021-12-08
      • 2022-06-24
      相关资源
      最近更新 更多