Сопоставление шаблонов переменных Erlang

У меня есть функция service_echo в простом приложении чата, которое использует SockJS для реализации многопользовательского приватного чата. Я создал таблицу ETS для списка онлайн-пользователей. Сохраняя сеанс SockJS, я думал отправлять сообщение этому соединению всякий раз, когда я получаю сообщение от другого соединения.

Вот мой код service_echo.

service_echo(Conn, {recv, Data}, state) ->
    Obj = mochijson2:decode(Data),
    {struct, JsonData} = Obj,
    Name = proplists:get_value(<<"name">>, JsonData),
    A = ets:lookup(username,Name),
    io:format("~p",[Conn]),
    if
      length(A) =:= 0 ->
          ets:insert(username,{Name,Conn});
      true ->
          [{AA,BB}] = ets:lookup(username,Name),

          BB:send(Data)
    end,

     io:format("hello");

Несмотря на то, что Conn и BB одинаковы, Conn:send(data) все равно отправляет в браузер правильные данные, а BB:send(Data) ничего не делает и даже не показывает ошибку. Поскольку я новичок в Erlang, прошу извинить меня за любые непреднамеренные ошибки.


person user2512324    schedule 14.08.2013    source источник
comment
Это действительно тот код, который вы использовали, или вы ввели его отдельно для StackOverflow? Например, у вас есть состояние со строчными буквами в первой строке, поэтому эта функция вообще никогда не будет работать. Чтобы помочь людям ответить, убедитесь, что вы показываете точный код, который пытаетесь запустить.   -  person RichardC    schedule 14.08.2013
comment
StateEcho = sockjs_handler:init_state( <<"/echo">>, fun service_echo/3, state, [{response_limit, 4096}]), вызывает функцию service_echo. Это код, который я запускаю, но сообщения не отправляются BB:send(Data).   -  person user2512324    schedule 14.08.2013
comment
Этот фрагмент кода не может быть скомпилирован, Var — в строке 12 — не привязан. Так что, как сказал Ричард, некоторая информация утеряна. В любом случае, чтобы иметь возможность помочь вам, может быть интересно узнать, что вы сохранили в BB, потому что именно функция send/1 в модуле BB отвечает за отправку сообщения - строка 13.   -  person Pascal    schedule 14.08.2013
comment
@Pascal Я немного отредактировал, прежде чем публиковать вопрос, чтобы упростить его. Спасибо. BB идентичен Conn, который представляет собой соединение SockJS через веб-сокеты. Вывод io:format для Conn будет выглядеть как {<0.161.0>, [{peername,{{127,0,0,1},56247}}, {sockname,{{127,0,0,1},56247}}, {path,"/echo/039/62l0slqe/websocket"}, {headers,[]}]}}. Что раздражает, так это Conn:send работает там, где BB, который совпадает с Conn через сопоставление с образцом, не работает как как работает Конн. BB:send() не работает.   -  person user2512324    schedule 14.08.2013


Ответы (1)


Прежде всего, позвольте мне посоветовать вам никогда не использовать length(A) =:= 0 для проверки того, является ли список A пустым или нет; если A длинный список, подсчет его элементов будет стоить вам дорого, хотя результат фактически не будет использован. Вместо этого используйте A =:= [], проще и лучше.

Я не понимаю, почему вы говорите, что Conn и BB одинаковы. Это не следует из кода, который вы разместили здесь. Если Name нет в таблице, вы вставляете запись {Name, Conn}. В противном случае, если Name существует в таблице и относится к одному объекту BB, вы предполагаете, что этот BB является модулем, и вы вызываете определенную в нем функцию send.

Возможно, вы неправильно читаете семантику if --- если это так, не позволяйте охраннику true сбить вас с толку, так в Erlang записывается if-then-else. Возможно, вы хотели иметь что-то вроде:

    ...
    A = ets:lookup(username,Name),
    if
      A =:= [] ->
        ets:insert(username,{Name,Conn})
    end,
    [{_,BB}] = ets:lookup(username,Name),
    BB:send(Data)
    ...

или еще лучше:

    ...
    A = ets:lookup(T,Name),
    if
      A =:= [] ->
        ets:insert(T,{Name,Conn}),
        BB = Conn;
      true ->
        [{_,BB}] = A
    end,
    BB:send(Data)
    ...

С другой стороны, может быть, я неправильно понял, что вы пытаетесь сделать. Если это так, пожалуйста, уточните.

person nickie    schedule 27.08.2013
comment
Спасибо, что дали больше информации. Моему подходу определенно не хватает эффективности. Но проблема в том, что BB, который извлекается после того, как [{_,BB}]=A появляется так же, как Conn, который является переменной SockJS, но не отправляет данные BB:send(data), но Conn:send(Data) работает. В таблице поиска ETS второй элемент кортежа идентичен экземпляру Conn. Но при извлечении после сопоставления с образцом не отправляет Data, как это делает Conn. Я думаю, что запутал всех здесь. Мои извинения. - person user2512324; 28.08.2013