De regreso en Scala

Soy un novato scala programador y llegó a través de un comportamiento extraño.

def balanceMain(elem: List[Char]): Boolean =
  {
    if (elem.isEmpty)
      if (count == 0)
        true;
      else false;

    if (elem.head == '(')
      balanceMain(elem.tail, open, count + 1);....

Anteriores, básicamente, quiero devolver true si elem.isEmpty y count == 0. De lo contrario, quiero devolver false.

Ahora encima he leído que no hay necesidad de agregar una instrucción return en la scala. Así que he omitido return arriba. Pero no devuelve el booleano. Si puedo añadir una instrucción return como return true. funciona a la perfección. ¿Por qué es así?

También, ¿por qué es considerado una mala práctica que ha devolución de las declaraciones en la scala

  • Hay generalmente no hay necesidad para el retorno de la palabra clave, siempre y cuando se rompe el código en pequeñas suficiente métodos.
  • Gracias. Por favor puede explicar? ¿Cómo va a hacerlo.
  • parece que está tomando el coursera scala curso. todo lo mejor 🙂
InformationsquelleAutor Jatin | 2012-09-24

6 Kommentare

  1. 122

    No es tan simple como la omisión de la return palabra clave. En Scala, si no hay return luego de la última expresión es el valor de retorno. Por lo tanto, si la última expresión es lo que desea devolver, entonces se puede omitir el return palabra clave. Pero si lo que quieres regresar es no la última expresión, entonces Scala no sabrá que usted quería volver.

    Un ejemplo:

    def f() = {
      if (something)
        "A"
      else
        "B"
    }

    Aquí, la última expresión de la función f es un if/else expresión que se evalúa como una Cadena. Ya que no hay ninguna explícita return marcado, Scala pensará que no quería devolver el resultado de este if/else expresión: una Cadena.

    Ahora, si queremos añadir algo después de la if/else expresión:

    def f() = {
      if (something)
        "A"
      else
        "B"
    
      if (somethingElse)
        1
      else
        2
    }

    Ahora, la última expresión es un if/else expresión que devuelve un Int. Así que el tipo de retorno de f será de tipo Int. Si realmente queríamos que devolver la Cadena, entonces estamos en problemas porque Scala ha ni idea de que es eso lo que se pretendía. Por lo tanto, tenemos que arreglarlo ya sea por el almacenamiento de la Cadena a una variable y regresar después de la segunda if/else expresión, o cambiando el orden, de modo que la Cadena de la parte que ocurra de último.

    Finalmente, se puede evitar la return palabra clave, incluso con un anidada if-else expresión como el tuyo:

    def f() = {
      if(somethingFirst) {
        if (something)      //Last expression of `if` returns a String
         "A"
        else
         "B"
      }
      else {
        if (somethingElse)
          1
        else
          2
    
        "C"                //Last expression of `else` returns a String
      }

    }

    • Por todos los Dioses, gracias! Yo estaba luchando con el mismo problema por horas (también de hacer el curso en Coursera) y no era capaz de entender por qué el regreso fue necesario.
    • para el primer ejemplo, ¿qué sucede si usted agregar devuelve. yo.e return "A" y return "B" ?
    • sería volver a la llamada de f() con el valor de «A» o «B». Pero como expliqué en mi respuesta. Nunca uso retorno en la Scala. Si las declaraciones en la Scala de trabajo de una manera funcional. Ellos evalúan a algo con un tipo. Como el operador ternario en Java (?:). Ejemplo: val foo = si (mybool) «Una» cosa «B» – foo será una Cadena que contiene, ya sea «A» o «B». Del mismo modo de pensar de una función no devuelve algo, pero a evaluar el valor de la última expresión en él.
  2. 20

    Este tema en realidad es un poco más complicado, como se describe en las respuestas hasta el momento. Este blogpost por Rob Norris explica en más detalle y da ejemplos de cuando se usa la devolución de romper su código (o al menos no tienen un efecto obvio).

    En este punto permítanme citar la esencia del post. La declaración más importante es la derecha en el comienzo. Imprimir este cartel y lo puso en su muro 🙂

    La return palabra clave no es «opcional» o «inferido»; cambia la
    significado de su programa, y nunca se debe utilizar.

    Da un ejemplo, donde de hecho se rompe algo, cuando en línea de una función

    //Inline add and addR
    def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) //inlined add
    
    scala> sum(33, 42, 99)
    res2: Int = 174 //alright
    
    def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) //inlined addR
    
    scala> sumR(33, 42, 99)
    res3: Int = 33 //um.

    porque

    Un return expresión, cuando se evalúan, se abandona a la corriente de la computación
    y devuelve al llamador del método en el que return aparece.

    Este es sólo uno de los ejemplos que se dan en el post vinculado y es el más fácil de entender. No tenemos más y les recomendamos que, para ir allí, de leer y de entender.

    Cuando vienen de lenguajes imperativos como Java, esto puede parecer extraño al principio, pero una vez te acostumbras a este estilo tiene sentido. Permítanme terminar con otra cita:

    Si te encuentras en una situación en la que usted piensa que usted desea regresar temprano, es necesario re-pensar la forma en que ha definido su cálculo.

    • No estoy de acuerdo con Rob, la OMI no debe utilizar return sólo en las expresiones lambda, pero esto es una mierda opción de diseño en la lengua, el código no debería compilar (en python esto es evitado por tener lambda palabra clave sin la instrucción return)… en cada uno de los otros casos, no veo un problema real en el uso de return si desea devolver un valor (y sí, a la salida de la ejecución del método, porque es lo que el retorno se utiliza en todos los idiomas!)
    • Eres libre de tener su opinión, pero mucha gente está de acuerdo que el uso de regreso en Scala es, al menos, de mal estilo. Me atrevo a encontrar oficial de la Scala doc ejemplos que uso retorno. Es AFAIK ni siquiera se explica en el documento oficial, sólo en el documento de especificaciones (cap 6.20). Cotización Martin Odersky sí mismo (Programación en Scala) «El estilo recomendado para los métodos es, de hecho, para evitar explícito, y, especialmente, múltiples, las sentencias return. En su lugar, pensar de cada método, como una expresión que produzca un valor que se devuelve.» Primera ed de este libro está disponible gratis en línea artima.com/pins1ed
  3. 4

    Yo no programa Scala, pero yo uso otro idioma con el implícito devuelve (Ruby). Usted tiene código después de su if (elem.isEmpty) bloque — la última línea de código es lo que se devuelve, que es la razón por la que usted no está consiguiendo lo que estás esperando.

    EDIT: he Aquí una manera más sencilla de escribir su función también. Sólo utilice el valor boolean isEmpty y contar para devolver true o false de forma automática:

    def balanceMain(elem: List[Char]): Boolean =
    {
        elem.isEmpty && count == 0
    }
    • Gracias. Pero yo sólo quiero regresar si elem.isEmpty && count ==0 return true else continuar con el bloque. La anterior devolverá incluso si es falsa.
    • Ah, no se dio cuenta de que. Principios y explicit retorno sería apropiado en este caso.
    • Tampoco está definido en la OP del código. Supuse que era una llamada de método.
  4. 4

    No escribir if declaraciones sin un correspondiente else. Una vez que se agrega el else a su fragmento verás que tu true y false son, de hecho, las últimas expresiones de la función.

    def balanceMain(elem: List[Char]): Boolean =
      {
        if (elem.isEmpty)
          if (count == 0)
            true
          else
            false
        else
          if (elem.head == '(')
            balanceMain(elem.tail, open, count + 1)
          else....
    • He aplicado, tiene 3 SI anidadas y se ve feo. ¿Hay algún patrón para hacer que se vea más bonito?
  5. 4

    Por defecto, la última expresión de una función será devuelto.
    En tu ejemplo no es otra expresión después de que el punto donde desea que su valor de retorno.
    Si desea devolver cualquier cosa antes de su última expresión, usted todavía tiene que usar return.

    Puede modificar su ejemplo como este, para devolver un Boolean de la primera parte

    def balanceMain(elem: List[Char]): Boolean = {
      if (elem.isEmpty) {
        //== is a Boolean resulting function as well, so your can write it this way
        count == 0
      } else {
        //keep the rest in this block, the last value will be returned as well
        if (elem.head == "(") {
          balanceMain(elem.tail, open, count + 1)
        }
        //some more statements
        ...
        //just don't forget your Boolean in the end
        someBoolExpression
      }
    }
    • No «declaración». «la expresión»
    • gracias por la sugerencia, lo corregimos.
  6. 0

    Caso de uso partido para el pronto regreso a propósito. Le obligará a declarar a todos los de retorno de las ramas de forma explícita, la prevención de la imprudente error de olvidar para volver a escribir en algún lugar.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea