Ruby para novatos iteradores y bloques

Ruby es uno de los idiomas más populares utilizados en la web. Hemos comenzado una nueva serie de capturas de pantalla aquí en Nettuts + que te presentará a Ruby, así como a los excelentes marcos y herramientas que acompañan el desarrollo de Ruby. En este capítulo, hablaremos de bloques e iteradores..


Alcanzar

  • Lección 1: Instalando Ruby y Comenzando
  • Lección 2: Variables, tipos de datos y archivos 
  • Lección 3: Trabajando con clases
  • Lección 4: Condicionales y Bucles
  • Lección 5: Iteradores y bloques

Ver Screencast


Bloques

En la última lección, hablamos de bucles. En realidad, no usarás loops demasiado a menudo en Ruby, debido a una característica llamada bloques (y-como resultado de bloques-iteradores). Para actualizar su memoria, observe las dos siguientes llamadas de método (puede intentar esto en IRB):

name = "Joe" name.reverse # => "eoJ" name.concat ("the Plumber") # => "Joe the Plumber"

Como saben, los paréntesis después de la llamada al método son generalmente opcionales. Aprenderemos hoy cuando sean requeridos..

Entonces, aquí están las partes de un método llamado:

  • El objeto que recibe el método; nombre encima.
  • El punto.
  • El nombre del método; marcha atrás o concat encima.
  • Los argumentos; " El fontanero" en el segundo ejemplo de arriba.
  • El bloque de código; Manténganse al tanto!

Las primeras tres partes son necesarias, obviamente. Los argumentos y el bloque de código son opcionales. ¿Qué es este bloque de código? Mira este ejemplo, y luego lo discutiremos:

sites = ["net", "psd", "mobile"] sites.map! hacer | sitio | site + = ".tutsplus.com" end sites # => ["net.tutsplus.com", "psd.tutsplus.com", "mobile.tutsplus.com"]

En este caso, la matriz. sitios es el receptor; el metodo es mapa!. A continuación tenemos el bloque. Si el bloque está en varias líneas, puede utilizar las palabras clave hacer y fin para delimitarlo. Si lo coloca en una sola línea, puede usar llaves (esto también funciona para bloques de varias líneas).

Después de la apertura del bloque, tenemos los parámetros del bloque, dentro de las tuberías ( | ). Lo que esto realmente depende del método que estás ejecutando. El uso más común de los bloques está en los métodos de iterador, por lo que el parámetro de bloque será el elemento actual en el bucle. Si esto suena bastante abstracto, haremos algunos ejemplos..


Iteradores

Comenzaremos observando los iteradores de los arreglos, porque son lo más comúnmente usado en bucle.

En lugar de usar un bucle for, probablemente usarás cada:

sites = ["net", "psd", "mobile"] sites.each | site | pone "# site .tutsplus.com" # net.tutsplus.com # psd.tutsplus.com # mobile.tutsplus.com

Esto es como hacer un bucle for; uno por uno, cada elemento en sitios será asignado al parámetro de bloque sitio; A continuación, se ejecutará el código dentro del bloque..

En caso de que tenga curiosidad, la cada método devuelve la matriz original.

A veces, querrás devolver un valor del bloque. Eso no es difícil de hacer, si usas el método correcto.

# asumir sitios por encima de sitios = sites.map do | s | "# s .tutsplus.com" fin

los mapa El método recopila los valores que se devuelven de cada iteración del bloque. Entonces, una matriz de esos valores se devuelve desde el método. En este caso, estamos reasignando el sitios variable a la nueva matriz.

Sin embargo, hay una mejor manera de hacer esto. Varios métodos de Ruby tienen duplicados con el signo de exclamación (o bang); esto significa que son destructivos: reemplazan el valor en el que están trabajando. Así que lo anterior podría hacerse de esta manera:

sitios.map! | site_prefix | "# site_prefix .tutsplus.com"

Ahora, sitios Será la matriz de valores devueltos desde el bloque..

Sin embargo, más que los arreglos tienen métodos iteradores. Los números tienen una buena onda veces método:

5 veces hacer | i | pone "número de bucle # i" final # número de bucle 0 # número de bucle 1 # número de bucle 2 # número de bucle 3 # número de bucle 4

A medida que continúe codificando Ruby, encontrará muchos métodos útiles que usan bloques. Ahora, veamos cómo crear nuestros propios bloques..


Bloques de construcción

Ahora que está familiarizado con el uso de bloques, veamos cómo escribir métodos que los aprovechen. Aquí hay otros dos tidbits de bloques que aún no has aprendido:

  • No se requieren parámetros de bloque; Puedes escribir un bloque que no los use..
  • Los propios bloques pueden ser opcionales. Puedes escribir una función que funcione con o sin bloques..

Esto es lo que sucede al que llamas método que toma un bloque. Detrás de las escenas, Ruby está ejecutando algún código de método, luego, cediendo al código de bloque. Después de eso, el control se devuelve al método. Vamos a ver.

Como la mayoría de las funciones de iterador simples están integradas en Ruby, "reescribiremos" una de esas. Vamos a hacer el cada método en matrices:

clase Array def each2 i = 0; mientras que self [i] produce self [i] i + = 1 end end end end

Como puedes ver, esto es solo un método normal. Recuerde que dentro de un método de instancia, el yo palabra clave se refiere a la instancia de la clase, en este caso, Formación. Dentro del método, estamos usando un bucle while para recorrer los elementos de la matriz. Luego, dentro del bucle, usamos el rendimiento palabra clave. Lo estamos pasando yo [i]; que terminará siendo el parámetro de bloque. Después de eso, incrementamos yo para el bucle y continuar.

Si quisiéramos que este método devolviera la matriz de valores que devolvió el bloque, simplemente podríamos capturar el valor devuelto de rendimiento y devolver eso, en lugar de yo, devolvemos esa matriz.

clase Array def each2_returning_new_values ​​i = 0; new_vals = []; mientras self [i] new_vals [i] = produce self [i] i + = 1 final new_vals end end

Métodos revisados

Terminemos hablando de métodos. Sabemos que usar paréntesis es opcional ... la mayor parte del tiempo. Aquí es cuando necesita usar el paréntesis cuando se llama al método.

A veces, tendrás ambos parámetros de método y un bloque..

obj.some_method "param" | x | #bloquea el código aquí

Lo que acabo de hacer no funcionará; Necesitamos usar paréntesis en este caso, porque de lo contrario el bloque está asociado con el último parámetro. Este es solo el caso si usa llaves para delimitar el bloque; si utiliza hacer - fin, los paréntesis no son necesarios.

El otro paréntesis de tiempo que se requiere es cuando se pasa un hash literal (no una variable que apunta a un hash) como el primer parámetro del método. Ruby pensará que es un bloque, debido a la llave

arr.push : name => "Andrew" # Fails! arr.push (: name => "Andrew") # Pases