2011-03-24 6 views
13

Digamos que tengo este código aquí:¿De qué manera las declaraciones de casos mango Erlang mezclan con la recursión de cola

do_recv_loop(State) -> 
    receive 
    {do,Stuff} -> 
     case Stuff of 
     one_thing -> 
      do_one_thing(), 
      do_recv_loop(State); 
     another_thing -> 
      do_another_thing(), 
      do_recv_loop(State); 
     _ -> 
      im_dead_now 
     end 
    {die} -> im_dead_now; 
    _ -> do_recv_loop(State) 
    end. 

Ahora, en teoría esto es recursiva de cola, ya que ninguna de las tres llamadas a do_recv_loop requerir cualquier cosa por estar devuelto. Pero ¿Erlang reconocerá que esto es recursivo de la cola y se optimizará apropiadamente? Me preocupa que la estructura anidada pueda hacer que no sea capaz de reconocerlo.

Respuesta

16

Sí, lo hará. Se requiere Erlang para optimizar las llamadas de cola, y esto es claramente una llamada de cola ya que no pasa nada después de que se llama a la función.

Solía ​​desear que hubiera una palabra clave tailcall en Erlang, por lo que el compilador podría advertirme sobre usos no válidos, pero luego me acostumbré.

+1

+1. Para cualquier lógica que sea ** provably ** tail-recursive, Erlang la optimiza según la definición del lenguaje. –

+0

Me alegra que te hayas acostumbrado porque 'tailcall' es una idea realmente horrible. –

-1

Soy bastante nuevo en Erlang, pero por lo que he recogido, la regla parece ser que para ser recursivo de cola, la función tiene que hacer una de dos cosas en cualquier rama lógica dada:

  • no hace una llamada recursiva
  • devolver el valor de la llamada recursiva y no hacer nada más después de que

Esa llamada recursiva se puede anidar en tantas if, case, o receive llamadas como desee siempre que n otra realidad sucede después de eso.

2

Esto pienso que es relevante porque usted pregunta cómo sabe si su función recursiva está optimizada por el compilador. Como no está utilizando listas: reverse/1, la siguiente puede no aplicarse, pero para otra persona con la misma pregunta pero con un ejemplo de código diferente, puede ser muy relevante.

del La Ocho mitos de rendimiento Erlang en la Guía de Eficiencia Erlang

En R12b y versiones posteriores, no es una optimización que será en muchos casos se reduce la cantidad de palabras utilizadas en la pila en llamadas recursivas de cuerpo, para que una función recursiva de recursividad de cuerpo y función recursiva de cola que llame a enumera: inverso/1 al final usará exactamente la misma cantidad de memoria .

http://www.erlang.org/doc/efficiency_guide/myths.html#id58884

creo que el llevar el mensaje es que puede que tenga que medir en algunos casos, para ver lo que va a ser mejor.

2

Sí, es cola recursiva. El principal motivo para tener en cuenta es si estás envuelto dentro de las excepciones. En ese caso, a veces la excepción necesita vivir en la pila y eso hará que algo que parezca recursivo de cola se convierta en algo engañosamente no tan.

La optimización de la llamada final es aplicable si la llamada está en posición de cola. La posición de la cola es la "última cosa antes de que regrese la función".Tenga en cuenta que en

fact(0) -> 1; 
fact(N) -> N * fact(N-1). 

la llamada recursiva a hecho es no en posición de la cola porque después de fact(N-1) se calcula, es necesario ejecutar la continuación N * _ (es decir, multiplicar por N).

Cuestiones relacionadas