Guía de estudio de Ruby on Rails Bloques, Procs y Lambdas

Ruby es un lenguaje con un conjunto de características poderosas: las más poderosas, sin duda, son Blocks, Procs y Lambdas. En resumen, estas funciones le permiten pasar código a un método y ejecutar ese código en un momento posterior. A pesar de utilizar regularmente estas funciones, muchos desarrolladores no entienden completamente las diferencias sutiles entre ellas..

Guías de estudio: Al solicitar un trabajo de programación, a menudo se le presentará un cuestionario que pretende determinar su nivel de conocimiento y experiencia en un tema determinado. Los diversos artículos de esta serie proporcionan soluciones condensadas a las preguntas que podría esperar ver en dichas pruebas..

Bloques

Un bloque es un código que se pasa implícitamente a un método mediante el uso de llaves., , o do ... end sintaxis. Es una convención común usar para bloques de una sola línea, y do ... end Para bloques multilínea. Por ejemplo, los siguientes bloques son funcionalmente iguales:

array = [1,2,3,4] array.map! hacer | n | n * n end => [1, 4, 9, 16] array = [1,2,3,4] array.map! | n | n * n => [1, 4, 9, 16]

La magia detrás de un bloque es la rendimiento palabra clave; difiere la ejecución del método de llamada para evaluar el bloque. El resultado del bloque, si lo hubiera, se evalúa mediante cualquier código restante en el método. los rendimiento La declaración también puede aceptar parámetros, que luego se pasan y se evalúan dentro del bloque. Atando esto juntos, un simple ejemplo de la mapa! El método anterior sería el siguiente:

clase Array def map! self.each_with_index do | value, index | auto [índice] = rendimiento (valor) extremo final fin

Esta simple representación de mapa! llama al each_with_index Método y reemplaza el elemento en el índice dado con el resultado del bloque. Si bien este es un ejemplo trivial de uso de bloques, es útil mostrar rendimientoel poder de Los usos de los bloques en Ruby son infinitos, y los usamos frecuentemente en nuestro código..


Procs

El ejemplo anterior demuestra una limitación menor de los bloques: son sintaxis y desechables. Tenemos que volver a escribir los bloques cada vez que los reutilizamos en diferentes arreglos, pero podemos almacenar un bloque para su uso posterior utilizando el objeto Ruby Proc. Podemos almacenar un Proc en una variable y luego pasarlo explícitamente a cualquier método que acepte un objeto que se pueda llamar. Reescribiendo el ejemplo anterior como un Proc se vería como el siguiente:

number_squared = Proc.new | n | n * n

Modifiquemos nuestro mapa! Método para aceptar y llamar al objeto Proc:

clase Array def map! (proc_object) self.each_with_index do | value, index | self [index] = proc_object.call (value) end end end array = [1,2,3,4] array.map! (number_squared) => [1, 4, 9, 16]

Tenga en cuenta que ya no utilizamos el rendimiento palabra clave; en su lugar, utilizamos directamente el llamada Método en el objeto Proc, pasándole el valor de la matriz. Recibimos el mismo resultado que antes, pero almacenamos nuestro bloque en una variable para reutilizarla más tarde..


Lambdas

La función Lambda es casi idéntica a Procs pero con dos diferencias clave. Primero, un lambda verifica el número de argumentos que recibe y devuelve un ArgumentError si no coinciden. Por ejemplo:

l = lambda "I'm a lambda" l.call => "I'm a lambda" l.call ('arg') ArgumentError: número incorrecto de argumentos (1 para 0)

En segundo lugar, los lambdas proporcionan rendimientos diminutos, lo que significa que cuando un Proc encuentra una declaración de retorno en su ejecución, detiene el método y devuelve el valor proporcionado. Por otro lado, Lambdas devuelve su valor al método, lo que le permite continuar:

def proc_math Proc.new return 1 + 1 .call return 2 + 2 end def lambda_math lambda return 1 + 1 .call return 2 + 2 end proc_math # => 2 lambda_math # => 4

Como puedes ver proc_math golpea la declaración de retorno dentro del Proc y devuelve el valor de 2. A diferencia de, lambda_math omite la declaración de devolución y evalúa 2 + 2 en su lugar.

Una nota final: Ruby 1.9 introduce la nueva sintaxis lambda "stabby" (representada con ->), que es funcionalmente idéntica a la sintaxis lambda tradicional, pero la sintaxis "stabby" es mucho más clara.


Conclusión

En esta guía de estudio, hemos cubierto las diferencias clave entre Bloques, Procs y Lambdas:

  • Los bloques son de un solo uso..
  • Procs existen como objetos.
  • Lambdas tiene estricta verificación de argumentos.

Para una revisión más profunda, recomiendo los siguientes recursos:

  • Guías de estudio de Rails aquí en Nettuts+
  • Documentación de Ruby Proc
  • Programación Ruby 1.9
  • Metaprogramming Ruby: Programa como los profesionales de Ruby