2010-09-22 9 views

Respuesta

47

Ignorando las funciones anidadas, siempre es posible reemplazar los cálculos de Scala con devoluciones con cálculos equivalentes sin devoluciones. Este resultado se remonta a los primeros días de la "programación estructurada", y se llama structured program theorem, inteligentemente.

Con funciones anidadas, la situación cambia. Scala te permite colocar un "retorno" enterrado en el interior de una serie de funciones anidadas. Cuando se ejecuta la devolución, el control salta de todas las funciones anidadas, al método interno que lo contiene (suponiendo que el método todavía se está ejecutando, de lo contrario se lanza una excepción). Este tipo de desenrollado de la pila podría hacerse con excepciones, pero no se puede hacer mediante una reestructuración mecánica del cálculo (como es posible sin funciones anidadas).

La razón más común por la que realmente desea regresar desde el interior de una función anidada es salir de un bloque de control de recursos o de imperativo. (El cuerpo de un imperativo para la comprensión se traduce a una función anidada, a pesar de que se parece a una declaración.)

for(i<- 1 to bezillion; j <- i to bezillion+6){ 
if(expensiveCalculation(i, j)){ 
    return otherExpensiveCalculation(i, j) 
} 

withExpensiveResource(urlForExpensiveResource){ resource => 
// do a bunch of stuff 
if(done) return 
//do a bunch of other stuff 
if(reallyDoneThisTime) return 
//final batch of stuff 
} 
+0

Gracias por la respuesta.Esto es muy informativo – Jus12

+0

Creo que esta es una respuesta más formal. Estoy interesado en la prueba del resultado que mencionas. ¿Puedes proporcionar algunas referencias? – Jus12

+0

Se agregó un enlace a wikipedia para el teorema del programa estructurado. –

26

Se proporciona con el fin de adaptarse a aquellas circunstancias en las que es difícil o engorroso organizar todas las rutas de flujo de control para que converjan en el extremo léxico del método.

Si bien es cierto, como dice Dave Griffith, que puede eliminar cualquier uso de return, a menudo puede ser más ofuscante hacerlo que simplemente cortar la ejecución corta con un return abierto.

Tenga en cuenta también que return regresa de los métodos, no de las funciones (literales) que se pueden definir dentro de un método.

+0

Sabía que esa era la respuesta. No puedo pensar en ningún ejemplo. – Jus12

+8

Afortunadamente para mí, no solicitó ningún ejemplo ... –

+0

+1 para ofuscantes –

2

que ver return como útil al escribir código de estilo imperativo, lo que generalmente significa I/Código O Si está haciendo código funcional puro, no necesita (y no debe usar) return. Pero con el código funcional puede necesitar holgazanería para obtener un rendimiento equivalente al código imperativo que puede "escapar antes" usando return.

3

Aquí es un ejemplo

Este método tiene un montón de si-else para controlar el flujo, porque no hay retorno (eso es lo que me encontré con, usted puede utilizar su imaginación para ampliarla). Tomé esto de un ejemplo de la vida real y lo modificó para ser un código ficticio (de hecho, es más que esto):

Sin Retorno:

def process(request: Request[RawBuffer]): Result = { 
     if (condition1) { 
     error() 
     } else { 
     val condition2 = doSomethingElse() 
     if (!condition2) { 
      error() 
     } else { 
      val reply = doAnotherThing() 
      if (reply == null) { 
      Logger.warn("Receipt is null. Send bad request") 
      BadRequest("Coudln't receive receipt") 
      } else { 
      reply.hede = initializeHede() 
      if (reply.hede.isGood) { 
       success() 
      } else { 
       error() 
      } 
      } 
     } 
     } 
    } 

y vuelta:

def process(request: Request[RawBuffer]): Result = { 
     if (condition1) { 
     return error() 
     } 

     val condition2 = doSomethingElse() 
     if (!condition2) { 
     return error() 
     } 

     val reply = doAnotherThing() 

     if (reply == null) { 
     Logger.warn("Receipt is null. Send bad request") 
     return BadRequest("Coudln't receive receipt") 
     } 

     reply.hede = initializeHede() 
     if (reply.hede.isGood) 
     return success() 

     return error() 
    } 

En mi opinión, la segunda es más legible e incluso más manejable que la primera. La profundidad de la sangría (con código bien formateado) es profunda y profunda si no utiliza una declaración de retorno. Y no me gusta :)

+2

Creo que los programadores de Scala bien entrenados (no yo) pueden seguir el primer fragmento con mayor claridad. – Jus12

+0

De hecho, es un poco de "sabor", depende del punto de vista de los desarrolladores. p.ej. Me gusta el más plano – yerlilbilgin

Cuestiones relacionadas