En Ruby, los bloques, procs y lambdas son formas de manejar funciones anónimas y son fundamentales para la programación funcional. Este tema es crucial para entender cómo Ruby maneja el código reutilizable y la programación de alto nivel.

Bloques

¿Qué es un Bloque?

Un bloque es una porción de código que puede ser pasada a un método y ejecutada. Los bloques en Ruby se delimitan con do...end o con llaves {...}.

Sintaxis de Bloques

# Usando do...end
[1, 2, 3].each do |num|
  puts num
end

# Usando llaves
[1, 2, 3].each { |num| puts num }

Ejemplo Práctico

def greet
  puts "Hello"
  yield if block_given?
  puts "Goodbye"
end

greet { puts "How are you?" }

Explicación:

  • yield ejecuta el bloque pasado al método greet.
  • block_given? verifica si se ha pasado un bloque.

Ejercicio

Escribe un método repeat que tome un número y un bloque, y ejecute el bloque ese número de veces.

def repeat(n)
  n.times { yield }
end

repeat(3) { puts "Hello!" }

Solución:

def repeat(n)
  n.times { yield }
end

repeat(3) { puts "Hello!" }

Procs

¿Qué es un Proc?

Un Proc es un objeto que encapsula un bloque de código, permitiendo almacenarlo en una variable, pasarlo como argumento y ejecutarlo en cualquier momento.

Sintaxis de Procs

my_proc = Proc.new { |name| puts "Hello, #{name}!" }
my_proc.call("Alice")

Ejemplo Práctico

def call_proc(my_proc)
  my_proc.call("Bob")
end

my_proc = Proc.new { |name| puts "Hello, #{name}!" }
call_proc(my_proc)

Explicación:

  • Proc.new crea un nuevo objeto Proc.
  • call ejecuta el código encapsulado en el Proc.

Ejercicio

Crea un Proc que tome un número y lo multiplique por 2, luego pásalo a un método que lo ejecute.

def execute_proc(my_proc, num)
  my_proc.call(num)
end

double = Proc.new { |n| n * 2 }
puts execute_proc(double, 5)

Solución:

def execute_proc(my_proc, num)
  my_proc.call(num)
end

double = Proc.new { |n| n * 2 }
puts execute_proc(double, 5)  # Output: 10

Lambdas

¿Qué es una Lambda?

Una lambda es similar a un Proc, pero con algunas diferencias en cómo maneja los argumentos y el retorno.

Sintaxis de Lambdas

my_lambda = lambda { |name| puts "Hello, #{name}!" }
my_lambda.call("Charlie")

Ejemplo Práctico

def call_lambda(my_lambda)
  my_lambda.call("Dave")
end

my_lambda = lambda { |name| puts "Hello, #{name}!" }
call_lambda(my_lambda)

Explicación:

  • lambda crea un nuevo objeto Proc con comportamiento de lambda.
  • call ejecuta el código encapsulado en la lambda.

Diferencias entre Procs y Lambdas

Característica Proc Lambda
Creación Proc.new { ... } lambda { ... } o -> { ... }
Comportamiento de Retorno Retorna del método que lo contiene Retorna solo de la lambda
Verificación de Argumentos No estricta Estricta

Ejercicio

Crea una lambda que tome dos números y los sume, luego pásala a un método que la ejecute.

def execute_lambda(my_lambda, a, b)
  my_lambda.call(a, b)
end

sum = -> (x, y) { x + y }
puts execute_lambda(sum, 3, 4)

Solución:

def execute_lambda(my_lambda, a, b)
  my_lambda.call(a, b)
end

sum = -> (x, y) { x + y }
puts execute_lambda(sum, 3, 4)  # Output: 7

Conclusión

En esta sección, hemos explorado los bloques, procs y lambdas en Ruby. Estos conceptos son fundamentales para la programación funcional y permiten escribir código más flexible y reutilizable. Asegúrate de practicar con los ejemplos y ejercicios proporcionados para consolidar tu comprensión.

En el próximo tema, profundizaremos en la metaprogramación, una característica avanzada de Ruby que permite escribir código que escribe código.

© Copyright 2024. Todos los derechos reservados