如何将类型记录为名称?
How to document a type as just a name?
查看 Erlang 文档,有时我会遇到类型规范,它记录了一个函数类型而没有真正指定类型...
很难解释,所以让我给你一个example。在 gen_server
中,handle_call
函数在文档中显示如下:
Request = term()
From = {pid(),Tag}
State = term()
Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
这里从未显示类型 Tag
(即它只是一个变量名)。
是否可以用edoc
做同样的事情?我找到的最接近的是不透明类型规范,但将其记录为 abstract - 是一样的吗?
据我所知,Edoc 无法做到这一点。
我试过使用这样的规范:
-spec foo(Something) -> term().
foo(X) ->
X.
虽然 Edoc 实际上对此很满意,并在文档中将类型规范指定为 foo(Something)
,但没有指定 Something
是什么,但编译器对此表示不满,并说:
type variable 'Something' is only used once (is unbound)
所以你必须写:
-spec foo(Something::_) -> term().
foo(X) ->
X.
显示为 foo(Something::term())
,从而给出了 Something
.
的类型规范
使用 Edoc-only 类型规范:
%% @spec foo(Something) -> term()
foo(X) ->
X.
Edoc 将 Something
视为应用于变量 X
的类型名称,并将 foo(X::Something)
放入文档中。
所以这两种方法都不能完全达到您想要的效果。
只要函数中的参数变量名称(在所有子句中)与 @spec
中使用的名称相同即可。例如。
%% @spec start_link(Args) -> {ok, pid()}
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
将生成以下文档
start_link(Args) -> {ok, pid()}
如果您有不同的名字,例如
%% @spec start_link(Args) -> {ok, pid()}
start_link(Num) when is_integer(Num) ->
gen_server:start_link(?MODULE, [], []);
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
它将生成为
start_link(Num::Args) -> {ok, pid()}
假设 Args 是一个类型。
我个人不建议使用 edoc @spec,而是使用 -spec,因为它们被 dialyzer 使用,因此可以被验证。
edoc 也可以从 -spec 生成文档。给定 -spec 和 @spec,edoc 覆盖 @spec 指令。
%% @spec start_link(Args) -> {ok, Pid}
-spec start_link(term()) -> {ok, pid()}.
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
以上将导致
start_link(Args) -> {ok, Pid}
从上面删除@spec 将导致
start_link(Args::term()) -> {ok, pid()}
查看 Erlang 文档,有时我会遇到类型规范,它记录了一个函数类型而没有真正指定类型...
很难解释,所以让我给你一个example。在 gen_server
中,handle_call
函数在文档中显示如下:
Request = term()
From = {pid(),Tag}
State = term()
Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
这里从未显示类型 Tag
(即它只是一个变量名)。
是否可以用edoc
做同样的事情?我找到的最接近的是不透明类型规范,但将其记录为 abstract - 是一样的吗?
据我所知,Edoc 无法做到这一点。
我试过使用这样的规范:
-spec foo(Something) -> term().
foo(X) ->
X.
虽然 Edoc 实际上对此很满意,并在文档中将类型规范指定为 foo(Something)
,但没有指定 Something
是什么,但编译器对此表示不满,并说:
type variable 'Something' is only used once (is unbound)
所以你必须写:
-spec foo(Something::_) -> term().
foo(X) ->
X.
显示为 foo(Something::term())
,从而给出了 Something
.
使用 Edoc-only 类型规范:
%% @spec foo(Something) -> term()
foo(X) ->
X.
Edoc 将 Something
视为应用于变量 X
的类型名称,并将 foo(X::Something)
放入文档中。
所以这两种方法都不能完全达到您想要的效果。
只要函数中的参数变量名称(在所有子句中)与 @spec
中使用的名称相同即可。例如。
%% @spec start_link(Args) -> {ok, pid()}
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
将生成以下文档
start_link(Args) -> {ok, pid()}
如果您有不同的名字,例如
%% @spec start_link(Args) -> {ok, pid()}
start_link(Num) when is_integer(Num) ->
gen_server:start_link(?MODULE, [], []);
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
它将生成为
start_link(Num::Args) -> {ok, pid()}
假设 Args 是一个类型。
我个人不建议使用 edoc @spec,而是使用 -spec,因为它们被 dialyzer 使用,因此可以被验证。
edoc 也可以从 -spec 生成文档。给定 -spec 和 @spec,edoc 覆盖 @spec 指令。
%% @spec start_link(Args) -> {ok, Pid}
-spec start_link(term()) -> {ok, pid()}.
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
以上将导致
start_link(Args) -> {ok, Pid}
从上面删除@spec 将导致
start_link(Args::term()) -> {ok, pid()}