2015-09-02 1 views
1

Я новичок в Erlang, поэтому, пожалуйста, пройдите на меня.Как понять заявление Эрланг о получении?

Я запутался, как получить выписку выполняется в Эрл, например:

loop() -> 
    receive 
     MessageA -> handlerA(); 
     MessageB -> handlerB() 
    end 

Если MessageA получен, и handlerA выполняется через некоторое время, MessageB принимается в почтовом ящике процессов , выполняется ли handlerB?

Я думаю, нет, так как я вижу много кода, рекурсии для выполнения приема заявления еще раз:

loop() -> 
    receive 
     MessageA -> 
      handlerA(), 
      loop(); 
     MessageB -> 
      handlerB(), 
      loop() 
    end 

Но вот проблема, если обработчик messageA включает в себя другие получить заявление, как это:

loop() -> 
    receive 
     MessageA -> 
      loop2(), 
     MessageB -> 
      handlerB(), 
      loop() 
    end 

loop2() -> 
    receive 
     MessageC -> 
      handlerC() 
      loop2() 
     MessageD -> 
      handlerD() 
      loop2() 
    end 

В этом случае это означает, что если я войду в обработчик MessageA, я никогда не смогу обработать MessageB?

И как я могу это решить? Поместив обработчик MessageB в loop2? Это выглядит не очень грациозно, особенно когда есть несколько уровней утверждений о приеме.

Есть ли лучший способ сделать это?

ответ

3

Следующий код означает «выполнить получение одного сообщения», поэтому, если вы хотите получать более одного, вам необходимо выполнить цикл. Типичный способ сделать это в Эрланге - это задуматься.

loop() -> 
    receive 
     MessageA -> handlerA(); 
     MessageB -> handlerB() 
    end 

В вашем последнем примере, это выглядит, как у вас есть какое-то государственная машина, где изменения в другое состояние, в то время как B остается в том же состоянии. Не обязательно проблема, что вы больше не можете получать сообщения A, когда находитесь в состоянии, в котором вы ожидаете сообщения C и D, но это будет зависеть от проблемного домена.

+0

Спасибо! Что, если я все еще ожидаю сообщения B при обработке C и D? Повторять ли обработчик B в цикле2? Это петли очень многословны. – NeoWang

2

У вас есть это.

Что касается вашего примера с циклом и loop2, такая реализация означает, что вы хотите выбрать какое-то новое поведение, когда вы получили messageA, и вы должны отказаться от сообщенияB, если оно поступит позже. (будьте осторожны, если вы используете MessageA с большой буквы, он станет именем переменной и будет соответствовать любому сообщению!). В этом случае имеет смысл, и вы должны добавить пункт мусора сообщение, чтобы удалить из messageB очереди и других неожиданных сообщений:

loop2() -> 
    receive 
     messageC -> 
      handlerC(), 
      loop2(); 
     messageD -> 
      handlerD(), 
      loop2(); 
     _ -> 
      loop2() 
    end. 

Другая возможность заключается в том, что вы реализуете вид государственной машины, то вы должны использовать OTP поведение gen_fsm.

Если это не так, то есть вы все еще хотите поймать сообщениеB, которое появится позже, я настоятельно рекомендую вам поддерживать один цикл и заботиться обо всех возможных сообщениях в одном операторе получения.

Смежные вопросы