2017-04-10 59 views
1

我是新來的Erlang和想實現一個簡單的功能如下:警告:使用運營商的「<」有沒有影響?

% * ChatServers is a dictionary of usernames with tuples of the form: 
% {server, Pid, Reference,LoggedInUsers} 
get_chat_server([], _) ->   
    undefined; 

get_chat_server([Key|_], ChatServers) -> 
    {server, Pid, Reference,LoggedInUsers} = dict:fetch(Key,ChatServers), 
    LoggedInUsers < 100, 
    {server, Pid, Reference,LoggedInUsers}; 

get_chat_server([_|T], ChatServers) ->   
    get_chat_server(T, ChatServers). 

基本上,我試圖做的是找到我的字典裏,其LoggedInUsers數的第一個元組是小於100

但是,一旦我編譯我的代碼,我得到以下2個警告:

main_server_distributed.erl:63:警告:使用運營商的 '<' 沒有 效果main_server_distributed.erl:66:WA rning:此子句不能 匹配,因爲在61行之前的條款總是匹配

我有序言中的一些經驗和我記憶所及,這是模式匹配和遞歸的有效使用。你能指出我在這裏做錯了什麼嗎?提前致謝。

回答

6

子句的正文(->右側的所有內容)不是要滿足的條件列表,而只是逗號分隔的要評估的表達式列表。除最後一個表達式以外的所有結果值都將被丟棄。因此,您的<比較的布爾值不會在任何地方使用。

0

main_server_distributed.erl:66:警告:本條款所不能比擬的 因爲線61前款總是匹配

你已經基本上寫着:

get_chat_server(NonEmptyList, ChatServers) -> 
    {server, Pid, Reference,LoggedInUsers} = dict:fetch(Key,ChatServers), 
    LoggedInUsers < 100, 
    {server, Pid, Reference,LoggedInUsers}; 

get_chat_server(NonEmptyList, ChatServers) ->   
    get_chat_server(T, ChatServers). 

因此,第一個子句總是與第二個子句匹配的任何東西匹配。更具體地講,在模式:

[Key|_] 

Key將匹配任何東西,_將匹配任何東西。同樣,在模式:

[_|T] 

_將匹配任何東西,T將匹配任何東西。

Riffing關@ dsmith的回答是:

-module(my). 
-export([get_chat_server/3, get_chat_server_test/0]). 

get_chat_server(_MaxLoggedIn, []=_Keys, _ChatServers) ->   
    none; 
get_chat_server(MaxLoggedIn, [Key|Keys], ChatServers) -> 
    get_chat_server(MaxLoggedIn, Keys, ChatServers, dict:fetch(Key, ChatServers)). 

get_chat_server(MaxLoggedIn, _, _, {_,_,_,LoggedInUsers}=ChatServer) when LoggedInUsers < MaxLoggedIn -> 
    ChatServer; 
get_chat_server(MaxLoggedIn, [Key|Keys], ChatServers, _ChatServer) -> 
    get_chat_server(MaxLoggedIn, Keys, ChatServers, dict:fetch(Key, ChatServers)). 

%--------- 

get_chat_server_test() -> 
    Keys = [a, c], 
    ChatServers = [ 
     {a, {server, a, a_, 200}}, 
     {b, {server, b, b_, 100}}, 
     {c, {server, c, c_, 30}} 
    ], 
    ChatServerDict = dict:from_list(ChatServers), 

    none = get_chat_server(10, [], ChatServerDict), 
    {server, c, c_, 30} = get_chat_server(50, Keys, ChatServerDict), 
    {server, c, c_, 30} = get_chat_server(150, Keys, ChatServerDict), 
    PossibleResults = sets:from_list([{server,a,a_, 200},{server,c,c_,30}]), 
    true = sets:is_element(
      get_chat_server(250, Keys, ChatServerDict), 
      PossibleResults 
      ), 
    all_tests_passed.  

您還可以使用高階函數,即dict:fold(),讓所有符合您要求的ChatServers的列表:

max_fun(Max, Keys) -> 
    fun(Key, {_,_,_,LoggedInUsers}=Server, Acc) -> 
      case lists:member(Key, Keys) andalso LoggedInUsers<Max of 
       true -> [Server | Acc]; 
       false -> Acc 
      end 
    end. 

在外殼:

44>  ChatServers = [ 
44>   {a, {server, a, a_, 200}}, 
44>   {b, {server, b, b_, 100}}, 
44>   {c, {server, c, c_, 30}} 
44>  ]. 
[{a,{server,a,a_,200}}, 
{b,{server,b,b_,100}}, 
{c,{server,c,c_,30}}] 

45> ChatServerDict = dict:from_list(ChatServers). 
{dict,3,16,16,8,80,48, 
     {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}, 
     {{[], 
     [[a|{server,a,a_,200}]], 
     [[b|{server,b,b_,100}]], 
     [[c|{server,c,c_,30}]], 
     [],[],[],[],[],[],[],[],[],[],[],[]}}} 

46> Keys = [a,c]. 
[a,c] 

47> MaxLoggedIn = 150. 
150 

50> F = my:max_fun(MaxLoggedIn, Keys). 
#Fun<fl.0.128553666> 

51> dict:fold(F, [], ChatServerDict). 
[{server,c,c_,30}] 
1

你可以這樣做...

get_chat_server([], _) ->   
     undefined; 

    get_chat_server([Key|T], ChatServers) -> 
     {server, Pid, Reference,LoggedInUsers} = dict:fetch(Key,ChatServers), 
     if 
      LoggedInUsers < 100 -> 
       {server, Pid, Reference,LoggedInUsers}; 
      true -> 
       get_chat_server(T, ChatServers) 
     end. 

或者這

get_chat_server([], _) ->   
     undefined; 

    get_chat_server([Key|T], ChatServers) -> 
     Result = dict:fetch(Key,ChatServers), 
     case Result of 
      {_, _, _, LoggedInUsers} when LoggedInUsers < 100 -> 
      Result; 
      _ -> 
      get_chat_server(T, ChatServers) 
     end.