Erlang Получение и правильная структура вызовов - PullRequest
1 голос
/ 20 января 2012

Можно ли сделать следующее в erlang и не генерировать сбой из-за проблем с кучей памяти?

loop() ->
   receive
      {drop, X}  -> drop(X);
      X -> handle(X)
   end.

handle(X) ->
   case X of
     ok -> loop()
   end.

drop(X) -> 
  case X of
     ok -> loop()
   end.

Ответы [ 2 ]

6 голосов
/ 20 января 2012

Достаточно легко попробовать и посмотреть, что получится:

-module(loop).
-compile(export_all).
loop() ->
   receive
      {drop, X}  -> drop(X);
   after 1000 ->
      erlang:display(catch erlang:error(noes)),
      drop(ok)
   end.

drop(X) ->
  case X of
     ok -> loop()
   end.

Если вы запустите loop: loop (), вы увидите, что он действительно не увеличивает стек. Если вы добавите a, 1 после вызова drop (ok) или loop (), вы увидите, что стек растет.

Итак, компилятор выясняет, что это хвостовой вызов, и оптимизирует его, даже если это не рекурсивный хвостовой вызов.

1 голос
/ 20 января 2012

Моя внутренняя догадка - нет, так как написанные функции не являются хвостовыми рекурсивными.

...