Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir 如何使用打字机和透析器?_Elixir - Fatal编程技术网

Elixir 如何使用打字机和透析器?

Elixir 如何使用打字机和透析器?,elixir,Elixir,在Elixir中,我如何记录函数将返回实现特定行为的模块 举一个简单的例子,假设我创建了一个由两个模块实现的GreeterBehavior行为: defmodule GreeterBehaviour do @callback say_hello(String.t) :: String.t end defmodule FormalGreeter do @behaviour GreeterBehaviour def say_hello(name) do "Good day t

在Elixir中,我如何记录函数将返回实现特定行为的模块

举一个简单的例子,假设我创建了一个由两个模块实现的
GreeterBehavior
行为:

defmodule GreeterBehaviour do
  @callback say_hello(String.t) :: String.t
end

defmodule FormalGreeter do
  @behaviour GreeterBehaviour

  def say_hello(name) do
    "Good day to you #{name}"
  end
end

defmodule CasualGreeter do
  @behaviour GreeterBehaviour

  def say_hello(name) do
    "Hey #{name}"
  end
end
然后,我想通过一个函数检索迎宾员,轻松地替换掉这些实现中的任何一个:

defmodule MyApp do
  def main do
    greeter().say_hello("Pete") |> IO.puts
  end

  @spec greeter() :: GreeterBehaviour # This doesn't work with dialyzer
  def greeter do
    FormalGreeter # Can easily be swapped to CasualGreeter
  end
end
透析器将成功检查
临时迎宾员
正式迎宾员
是否正确执行
迎宾员行为
行为。但是,如何定义类型规范,以便透析器检查
greeter/0
返回的模块是否实际实现了
GreeterBehavior

使用
@spec greeter()::greeterbehavior
不起作用,因为透析器会发出警告:

lib/my_app.ex:19: Invalid type specification for function 'Elixir.MyApp':greeter/0. The success typing is () -> 'Elixir.FormalGreeter'

在您的行为中,您可以定义一个类型,用于
打招呼

@type f :: (String.t() -> String.t())
您的
迎宾员
函数可以返回一个模块+函数:
&module.say_hello/1

规范是:

@spec greeter() :: GreeterBehaviour.f()

这是一个好问题,我不确定是否可以在typespec中指定行为,我认为您可以将其作为spec
@spec greeter()::FormalGreeter
,以便透析器知道您返回的确切模块(在您的情况下,即使没有规范,它也会知道)然后,它可能会检查您是否正在调用不存在的模块上的函数;我也希望是这样。投票支持此功能。我不确定类型规格,但我倾向于使用配置(
config:my\u app,greeter\u module:FormalGreeter
)@DerekKraan我认为这是一个激励性的例子,可以解释为什么这样做会很好,例如,如果在配置文件中配置了错误的模块,则可以捕获。
defmodule GreeterBehaviour do
  @type f :: (String.t() -> String.t())
  @callback say_hello(String.t()) :: String.t()
end

defmodule FormalGreeter do
  @behaviour GreeterBehaviour

  def say_hello(name) do
    "Good day to you #{name}"
  end
end

defmodule CasualGreeter do
  @behaviour GreeterBehaviour

  def say_hello(name) do
    "Hey #{name}"
  end
end

defmodule MyApp do
  def main do
    greeter().("Pete") |> IO.puts()
  end

  # This will work with dialyzer
  @spec greeter() :: GreeterBehaviour.f()
  def greeter do
    # Can easily be swapped to CasualGreeter
    &FormalGreeter.say_hello/1
  end
end