警告:使用运营商'<'没有效果?

时间:2017-04-10 15:51:56

标签: erlang otp

我是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:警告:使用运营商&#39;&lt;&#39;没有   effect main_server_distributed.erl:66:警告:此子句不能   匹配,因为第61行的前一个句子始终匹配

我对prolog有一些经验,据我所知,这是模式匹配和递归的有效用法。你能指出我在这里做错了什么吗?提前致谢。

3 个答案:

答案 0 :(得分:6)

子句的主体(->右侧的所有内容)不是要满足的条件列表,而只是要用于评估的逗号分隔的表达式列表。除最后一个表达式之外的所有结果值都将被丢弃。因此,<比较的布尔值不会在任何地方使用。

答案 1 :(得分: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.

答案 2 :(得分: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将匹配任何内容。

重温@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.

在shell中:

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}]