我认为你在正确的轨道上。如果您添加一个@callback 来为“抽象”函数定义spec,那就更好了。我将用一个工作示例进行解释:
defmodule Fibonacci do
@callback fib(number :: integer) :: integer
defmacro __using__(_) do
quote do
@behaviour Fibonacci
def fibonacci(n) when not is_integer(n), do: {:error, "Not integer"}
def fibonacci(n) when n < 0, do: {:error, "Negative number"}
def fibonacci(n), do: {:ok, __MODULE__.fib(n)}
def fibonacci!(n) do
case fibonacci(n) do
{:error, reason} -> raise reason
{:ok, n} -> n
end
end
end
end
end
每个使用Fibonacci 的模块都需要实现回调函数fib/1。此外,use 和 Fibonacci 模块的每个模块都将具有处理错误的函数 fibonacci/1 和引发错误的 fibonacci!/1。
那么,让我们用直接递归来实现fib/1:
defmodule Direct do
use Fibonacci
def fib(0), do: 0
def fib(1), do: 1
def fib(n), do: fib(n - 1) + fib(n - 2)
end
对于尾递归:
defmodule Tail do
use Fibonacci
def fib(0), do: 0
def fib(1), do: 1
def fib(n), do: fib(1, 1, n - 2)
defp fib(_, value, 0), do: value
defp fib(n_2, n_1, n), do: fib(n_1, n_2 + n_1, n - 1)
end
所以在iex 中我们可以调用不同的实现:
iex(1)> Direct.fibonacci(10)
{:ok, 55}
iex(2)> Tail.fibonacci!(10)
55
iex(3)> Tail.fibonacci!(-10)
** (RuntimeError) Negative number
另外,如果你忘记在你的模块中定义 fib/1 函数,那么编译器会警告你:
defmodule Warning do
use Fibonacci
end
* warning: undefined behaviour function fib/1 (for behaviour Fibonacci)
如果您想使用此代码,只需点击此链接
http://elixirplayground.com?gist=606fe8c283443f03c7af08f85c888fe3
我希望这能回答你的问题。