Elixir - 为什么@callback定义中需要类型规范?

时间:2018-02-21 06:16:15

标签: types module elixir behavior

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

我的问题是:

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

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

    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
    

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

在旧版本的erlang中,它不是必需的。沿线的某个地方(我不记得确切的时间),人们意识到,如果添加它们,则Dialyzer可以进行一些其他验证。

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

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