Erlang接收和正确的呼叫结构

BAR*_*BAR 1 memory heap erlang

可以在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.
Run Code Online (Sandbox Code Playgroud)

Luk*_*kas 6

尝试看看会发生什么很容易:

-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.
Run Code Online (Sandbox Code Playgroud)

如果你运行loop:loop(),你会发现它确实没有增加堆栈.如果在调用drop(ok)或loop()之后添加1,则会看到堆栈在增长.

所以编译器发现它是一个尾调用并优化它,即使它不是一个递归的尾调用.