Объявление Typespec для возвращаемого значения переданной функции - PullRequest
0 голосов
/ 08 мая 2018

Допустим, у меня есть такая функция:

def something(callback) do
  case *some condition* do
    0 ->
     :ok
    1 ->
      {:error, :foo}
    _ ->
      callback.()
  end
end

, где функция обратного вызова может возвращать либо :ok, либо {:error, *some atom*}, где некоторый атом - неизвестный атом.

Теперь мне интересно, есть ли способ написать спецификацию для функции something/1, которая не использует общую спецификацию atom.Таким образом, вопрос, в основном, заключается в том, есть ли способ написать более конкретную спецификацию типов, чем эта:

@spec something(() -> :ok | {:error, atom}) :: :ok | {:error, atom}

Вместо этого я хотел бы, чтобы моя спецификация показывала, что функция something/1 может возвращать :ok, {:error, :foo} или значение, возвращаемое callback

PS Я знаю, что такого рода вещи не имеют значения на практическом уровне, поэтому это просто вопрос, основанный на любопытстве.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Вы ищете переменные типа. Erlang поддерживает их объявление, но в настоящий момент диализатор, похоже, не выполняет никаких проверок на основе этих типов (Erlang / OTP 20).

Переменные типа могут использоваться в спецификациях для определения отношений для входных и выходных аргументов функции. Например, следующая спецификация определяет тип полиморфной функции идентичности:

-spec id(X) -> X.

Подпись типа, которую вы хотите:

@spec something(() -> t) :: :ok | {:error, atom()} | t
0 голосов
/ 08 мая 2018

Вы можете определить @type для типа возврата callback/0, например @type callback_return_type :: atom и затем используйте: @spec something(fun()) :: :ok | :error | callback_return_type

PS Я знаю, что подобные вещи не имеют значения на практике. уровень, так что это просто вопрос, основанный на любопытстве.

Возможность компоновки Typespec имеет значение в больших проектах для обеспечения согласованности и предотвращения дублирования кода Типы, которые вы объявляете в module, могут быть повторно использованы другими modules, и вы даже можете объявить определенные typespecs как private и opaque, что дает вам точный гранулярный контроль над тем, как они должны использоваться и т.д. что вы можете поддерживать разделение интересов для пользователей библиотеки, например.

...