2009-12-08 35 views
6

Tengo una función en la que tengo una serie de declaraciones de casos individuales.Erlang: al regresar de una función

case ... of 
    ... 
end, 

case ... of 
    ... 
end, 

... 

etc.

Quiero volver a la función de inmediato cuando una condición caso particular se produce en uno de los estados de caso - para que la próxima declaración de caso no está marcada, y la función acaba de salidas/devoluciones. ¿Cómo puedo hacer eso?

Respuesta

13

yo sugeriría que refactorizar para aprovechar todo el poder de Erlang y sus capacidades de coincidencia de patrones.

no hay un operador return. Además, un hecho poco conocido es que se puede hacer algo como:

Return=case ... of

una declaración case puede tener un valor de "retorno".

+1

Es por eso que se llama una expresión de caso. – Christian

+0

Sí, eso es algo que vale la pena saber! Gracias. – jeffreyveon

+0

@jeffreyveon: ¿mi respuesta satisface su pregunta? – jldupont

4

Erlang no tiene un operador de return. Necesitará refactorizar su código en funciones más pequeñas.

Su código original tiene dos expresiones case encadenados con el operador coma. Supongo que tiene algunos efectos secundarios en la primera expresión de caso que desea conservar. A continuación, estoy usando un imaginario return operador:

case ... of 
    P1 -> return E1; 
    P2 -> E2; 
end, 

case ... of 
    ... 
end 

una expresión como esta se puede convertir en código Erlang real utilizando pequeñas funciones y coincidencia de patrones con algo parecido a esto:

case1(P1, ...) -> E1; 
case1(P2, ...) -> E2, case2(...). 
case2(...) -> ... 

Negación: Es Han pasado 10 años desde que escribí el código de Erlang, por lo que mi sintaxis puede estar desactivada.

+0

Sírvanse proporcionar un ejemplo de ello. –

+0

Ejemplo agregado, espero que ayude. –

2

En Erlang que acaba de utilizar la coincidencia de patrones para activar la función apropiada. Si tiene demasiadas cláusulas para cubrir y tratar, también sugeriría refactorizar el código un poco.

0

uso de captura/tirar

La persona que llama dice:

 
X = (catch foo(A, B)). 

luego escribir

 
foo(A, B) -> 
    case ... of 
    ...throw(X) .. 
    end, 

    case ... of 
    ... throw (Y) 
    end, 
    ... 

En general, esto se considera una práctica de programación - ya que el programa tiene múltiples puntos de salida y es difícil de cultivar

+2

Lanzar en Erlang es específicamente para devoluciones no locales, no para manejo de errores, por lo que en principio este es un enfoque válido. En la práctica, sospecho que refactorizar para evitarlo sería mejor aquí, pero sin ver el código es difícil saberlo. – cthulahoops

+2

En principio, podría ser un enfoque válido, y de hecho se trata de retornos no locales, pero todavía es una mala práctica usarlo ampliamente en su código. El uso de devoluciones no locales hace que sea muy difícil para otros programadores entender el código y dificulta la depuración. Si bien no está diseñado específicamente para el manejo de errores, el manejo de errores generalmente es el único lugar donde debe usarlo. Además, si está codificando el manejo de errores, no está siguiendo una filosofía central de Erlang, que es "código para el éxito": está pensando más como un programador imperativo. – Tim

12

P coincidente attern es una buena manera de refactorizar una declaración de caso - se puede hacer algo como esto

testcase(1, X, Y) -> .... passed1; 
testcase(2, X, Y) -> .... passed2; 
testcase(N, X, Y) when N > 2 -> .... passedlarge; 
testcase(_, X, Y) -> defaultcase. 

y después de su declaración de caso simplemente se envuelve hasta:

X = testcase(Number, Param1, Param2). 

(X será o passed1, passed2 , passedlarge o defaultcase en este ejemplo artificial)

+1

Ok, se ve increíble, gracias! – jeffreyveon

2

Una forma es poner en cascada sus declaraciones de caso:

my_fun(X) -> 
    case cond1(X) of 
    true -> ret1; 
    _ -> 
     case cond2(X) of 
     true -> ret2; 
     _ -> 
      ... 
     end 
    end. 

Otra es la de separar sus estados de cuenta de casos en cláusulas:

my_fun(X) -> 
    my_fun(cond1, X). 

my_fun(cond1, X) -> 
    case cond1(X) of 
    true -> ret1; 
    _ -> my_fun(cond2, X) 
    end; 

my_fun(cond2, X) -> 
    case cond2(X) of 
    true -> ret2; 
    _ -> my_fun(cond3, X) 
    end; 

... 
Cuestiones relacionadas