2016-04-04 37 views
2

看着二郎文檔,有時我遇到類型規格,該文檔的功能型沒有真正指定類型...如何將一個類型記錄爲一個名稱?

很難解釋,所以讓我給你一個example。在gen_serverhandle_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是否可以做同樣的事情?我發現最接近的是不透明的類型規格,但是它將它記錄爲抽象 - 是這樣嗎?

回答

2

只要函數中的變量名稱(在所有子句中)和在@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()} 

假設參數數量的類型。

我個人不推薦使用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()} 
+0

同意,建議不要使用EDOC @spec,而使用-spec。 –

0

據我所知,這對Edoc來說是不可能的。

我試圖用這樣的規格:

-spec foo(Something) -> term(). 
foo(X) -> 
    X. 

雖然電子文檔實際上是感到高興,並給出了型號規格作爲文檔foo(Something)沒有指定什麼Something,編譯器抱怨它,並說:

type variable 'Something' is only used once (is unbound) 

所以你必須寫:

-spec foo(Something::_) -> term(). 
foo(X) -> 
    X. 

,其顯示爲foo(Something::term()),由此給出Something的類型說明。

使用一個僅EDOC型規格:

%% @spec foo(Something) -> term() 
foo(X) -> 
    X. 

EDOC對待Something作爲適用於該可變X並提出foo(X::Something)文檔中類型名稱。

因此,這兩種方法都無法達到您想要的效果。

相關問題