42 - Bloques: argumentos

Un bloque puede recibir datos desde el método. Los argumentos se indican entre los caracteres | |, si son más de uno se separan por coma.

Ya utilizamos la sintaxis de argumentos cuando trabajamos con las clases Array, Hash etc.:

arreglo.each do |elemento| 
  print elemento
  print "-" 
end

El argumento se llama elemento y recibe en cada ejecución del bloque un valor del Array.

Veremos ahora como podemos implementar métodos que reciban bloques y le pasen a los mismos argumentos.

Programa: ejercicio160.rb

def metodo
  puts "primer instrucción del método"
  yield "naranjas", 23
  puts "última instrucción del método"
end


metodo do |producto, precio| 
 puts "Artículo #{producto}"
 puts "Precio #{precio}"
end

El resultado de ejecutar este programa es:

bloques en Ruby con argumentos

El bloque tiene dos argumentos que llamamos producto y precio, solo dentro del bloque se tiene acceso a los valores de los argumentos:

metodo do |producto, precio| 
 puts "Artículo #{producto}"
 puts "Precio #{precio}"
end

Desde el método enviamos los valores a los argumentos luego de yield:

  yield "naranjas", 23

Problema:

Desarrollar una clase que almacene las notas de 5 alumnos.
Plantear un método que mediante un bloque reciba como argumento las notas de alumnos que tienen una nota mayor o igual a 7, imprimir dichas notas y su promedio.

Programa: ejercicio161.rb

class NotasAlumnos

  def initialize
    @notas = [9, 7, 2, 5, 10]
  end

  def promocionados
    @notas.each do |nota|
      if nota >= 7
        yield nota
      end
    end
  end

 end


notas_alumno = NotasAlumnos.new()
suma = 0
cant = 0
notas_alumno.promocionados do |nota|
  puts "Nota del alumno: #{nota}"
  suma = suma + nota
  cant = cant + 1
end
promedio = suma / cant
puts "Promedio de notas de alumnos promocionados:#{promedio}"

Hemos planteado una clase donde en el método initialize definimos un atributo de tipo Array donde almacenamos las 5 notas de los alumnos:

class NotasAlumnos

  def initialize
    @notas = [9, 7, 2, 5, 10]
  end

El método promocionados debe iterar el Array @notas y cada vez que el valor sea mayor o igual a 7 procedemos a llamar a yield y pasar como parámetro la nota:

  def promocionados
    @notas.each do |nota|
      if nota >= 7
        yield nota
      end
    end
  end

Creamos un objeto de la clase NotasAlumnos e inicializamos un acumulador y un contador:

notas_alumno = NotasAlumnos.new()
suma = 0
cant = 0

Llamamos seguidamente al método promocionados y le pasamos como bloque la impresión de la nota (como sabemos solo se imprimirá si es mayor o igual a 7)

También dentro del bloque sumamos la nota y la contamos:

notas_alumno.promocionados do |nota|
  puts "Nota del alumno: #{nota}"
  suma = suma + nota
  cant = cant + 1
end

En un bloque podemos acceder a variables definidas previamente como son suma y cant.

Finalmente cuando sale del método promocionados procedemos a calcular el promedio y mostrarlo:

promedio = suma / cant
puts "Promedio de notas de alumnos promocionados:#{promedio}"

Problema propuesto

  • Plantear un método que le enviemos como parámetro un número entero y mediante un bloque se muestre por pantalla cada uno de los valores de la tabla de multiplicar que lleguen como argumento.
Solución
ejercicio162.rb

def tabla(nro)
  for x in 1..10
    ta = x * nro
    yield x, ta
  end
end

tabla(10) { |valor, ta| puts "10 * #{valor} = #{ta}" }