Capítulo 19. Objetos procedimiento

A menudo es deseable tener la posibilidad de definir repuestas específicas a sucesos inesperados. Resulta que esto se consigue con gran sencillez si podemos pasar un bloque de código a otros métodos, lo que significa que deseamos tratar el código como si fuesen datos.

Un objeto procedimiento nuevo se obtiene utilizando proc:

  ruby> quux = proc {
  ruby|   print "QUUXQUUXQUUX!!!\n"
  ruby| }
  #<Proc:0x401c4884>
  

Ahora quux referencia a un objeto y como las mayoría de los objetos, tiene un comportamiento que se puede invocar. Concretamente, podemos pedir que se ejecute a través de su método call

  ruby> quux.call
  QUUXQUUXQUUX!!!
  nil
  

Luego, después de todo esto. ¿Podemos utilizar quux cómo un argumento de un método? Ciertamente.

  ruby> def run ( p )
  ruby|   print "Vamos a llamar a un procedimiento ... \n"
  ruby|   p.call
  ruby|   print "Finalizado. \n"
  ruby| end
  nil
  ruby> run quux
  Vamos a llamar a un procedimiento ...
  QUUXQUUXQUUX!!! 
  Finalizado.
  nil
  

El método trap nos permite asignar una respuesta personalizada a cualquier señal del sistema.

  ruby> inthandler = proc{ print "^C ha sido pulsado.\n" }
  #<Proc:0x401c4104>
  ruby> trap "SIGINT", inthandler
  nil
  

Normalmente, al pulsar ^C se sale del interprete. Ahora se imprime un mensaje y el interprete sigue ejecutándose, así no se pierde el trabajo realizado. (No nos encontramos atrapados en el interprete para siempre; todavía se puede salir tecleando exit o pulsando ^D.)

Una observación final antes de pasar a otros temas: no es necesario dar al objeto procedimiento un nombre antes de asociarlo a una señal. Un objeto procedimiento anónimo equivalente se asemejaría a:

  ruby> trap "SIGINT", proc{ print "^C ha sido pulsado.\n" }
  #<Proc:0x401c4104>
  

O de una forma más compacta todavía,

  ruby> trap "SIGINT", 'print "^C ha sido pulsado.\n"'
  #<Proc:0x401c3d44>
  

Este formato abreviado es mas adecuado y legible cuando se escriben pequeños procedimientos anónimos.