2017-04-10 57 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.