¿Por qué la instrucción if en erlang admite solo algunas funciones específicas en su guardia?

Es decir

ok(A) ->
  if
    whereis(abc)=:=undefined ->
            register(abc,A);
    true -> exit(already_registered)
  end.

En este caso, obtenemos el error de "guardia ilegal".

Cuál sería la mejor práctica para usar los valores de retorno de la función como condiciones.

1
Antriksh Chaudhary 14 feb. 2018 a las 12:22

2 respuestas

La mejor respuesta

Procedente de otros lenguajes de programación, el if de Erlang parece extrañamente restrictivo y, de hecho, no se usa mucho, y la mayoría de la gente opta por usar case en su lugar. La distinción entre los dos es que, si bien case puede probar cualquier expresión, if solo puede usar Expresiones de protección.

Como se explica en el enlace anterior, las expresiones de protección están limitadas a funciones conocidas que están garantizadas para estar libres de efectos secundarios. Hay varias razones para esto, la mayoría de las cuales se reducen a la previsibilidad e inspeccionabilidad del código. Por ejemplo, dado que la coincidencia se realiza de arriba hacia abajo, las expresiones de protección que no coincidan se ejecutarán hasta que se encuentre una que sí lo haga. Si esas expresiones tuvieran efectos secundarios, fácilmente podrían generar resultados impredecibles y confusos durante la depuración. Si bien aún puede lograr eso con las expresiones case, si ve un if, puede saber que no se introducen efectos secundarios en la prueba sin necesidad de verificar.

Una última cosa, pero importante, es que los guardias deben terminar. Si no lo hicieran, la reducción de la llamada a una función podría continuar para siempre, y como el planificador se basa en reducciones, eso sería muy malo de hecho, con poco que hacer cuando las cosas van mal.

Como contraejemplo, puede matar de hambre al programador en Go exactamente por esta razón. Debido a que el programador de Go (como todos los programadores de microprocesos) es multitarea cooperativamente, tiene que esperar a que ceda una goroutine antes de poder programar otra. Al igual que en Erlang, espera a que una función termine lo que está haciendo actualmente antes de poder continuar. La diferencia es que Erlang no tiene bucles iguales. Para lograr el bucle, recurre, lo que necesita una llamada / reducción de función, y permite un punto para que intervenga el programador. En Go, tiene bucles de estilo C, que no requieren una llamada a función en su cuerpo, por lo que un código similar a for { i = i+1 } dejará sin aliento al programador. No es que esos bucles sin llamadas a funciones en su cuerpo sean muy comunes, pero este problema existe.

Por el contrario, en Erlang es extremadamente difícil hacer algo como esto sin proponerse hacerlo explícitamente. Pero si los guardias contenían un código que no terminaba, se volvería trivial.

0
Brian Cully 17 feb. 2018 a las 15:51

Verifique esta pregunta: Acerca del uso de "if" en el idioma Erlang

En resumen:

Solo se permite un número limitado de funciones en las secuencias de protección, y dónde no es una de ellas

Utilice case en su lugar.

2
Elvis Oric 14 feb. 2018 a las 09:38