2016-07-12 4 views
1

Я вижу функции, которые заключают в себе блок приема, называемый рекурсивно, по-видимому, не в положении хвоста по всему месту в примере кода эликсира. Например:Рекурсия хвоста в принимающем блоке

defmodule A do 
    def loop do 
    receive do 
     :ping -> 
     IO.puts "Received :ping" 
     loop # <- Tail position? 
     :pong -> 
     IO.puts "Received :pong" 
     loop # <- Also Tail position? 
     after 
     5000 -> 
      loop # <- Also Tail position? 
    end 
    loop # <- Also Tail position? 
    end 
end 

ли получить специальную конструкцию, которая оптимизирует для хвостовых позиций в конце всех блоков матча? Если это применимо, если блок приема имеет блок after? Что делать, если есть код после блока приема в функции?

ответ

5

В вашем примере только последний звонок loop является хвостом рекурсивным. Вместо того, чтобы делать рекурсивный вызов внутри блока receive, просто верните receive и просто используйте хвостовой рекурсивный вызов для цикла в конце уже существующей функции.

defmodule A do 
    def loop do 
    receive do 
     :ping -> 
     IO.puts "Received :ping" 
     :pong -> 
     IO.puts "Received :pong" 
     after 
     5000 -> 
      nil 
    end 
    loop 
    end 
end 

Как правило, циклы процесса всегда должны иметь ровно один рекурсивный вызов в конце функции loop. Это самый простой способ гарантировать бесконечный цикл процесса.

Однако, вы можете петли внутри receive блока, если это последнее утверждение в функции loop. Результат будет также рекурсивным. Это позволяет условно остановить цикл, основанный на принятом сообщении

defmodule A do 
    def loop do 
    receive do 
     :ping -> 
     IO.puts "Received :ping" 
     loop 
     :pong -> 
     IO.puts "Received :pong" 
     loop 
     :stop -> 
     IO.puts "Bye Bye" 
    end 
    end 
end 

Также см http://erlang.org/doc/efficiency_guide/processes.html#id69762

+0

Awesome, спасибо! Эти документы erlang были именно тем, что я искал. – greggreg

+0

Я предполагаю, что то же самое верно для 'case' и т. Д.? Что функция, называемая рекурсивно из условия в 'case', является TCO, при условии, что после блока ничего не вызывается? – kevlarr

+0

Да, это должно применяться и в этих ситуациях. –

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