Otras características

P: ¿Qué significa a ? b : c?
P: ¿Cómo puedo contar el número de líneas de un fichero?
P: ¿Qué devuelven begin y end de MatchingData?
P: ¿Como puedo sumar los elementos de un array?
P: ¿Cómo se utilizan las "continuaciones"?

P: ¿Qué significa a ? b : c?

R: Es lo mismo que decir if a then b else c end.

P: ¿Cómo puedo contar el número de líneas de un fichero?

R: Suponiendo que cada línea finaliza con sólo un salto de línea, los resultados más rápidos se obtienen con:

	    open("example").read.count("\n")       # -> 3
	  

P: ¿Qué devuelven begin y end de MatchingData?

R: Actúan con $ y devuelven el índice inicial y final de la coincidencia ($0) en la cadena origen. Se puede ver un ejemplo en la expansión de tabuladores en la sección 9 punto 17.

P: ¿Como puedo sumar los elementos de un array?

R: En vez de solucionar este problema concreto, vamos a solucionar uno más general. La primera cosa que vamos a hacer es generar un método que itere sobre un objeto Enumerable y que obtenga un resultado único. Smalltalk llama es este método inject, y así lo haremos nosotros:

	    
	    module Enumerable
	      
	      # inject(n) { |n, i | ... }
	      def inject(n)
	        each { |i|
		  n = yield(n,i)
		}
		n
	      end
	    end
	  
Obsérvese que el método se ha añadido al módulo Enumerable. Esto implica que cualquier clase que lo incluya puede desde ese momento utilizar inject.Pero, ¿cómo lo utilizamos? sólo posee un argumento "n" y un bloque. Para cada elemento del objeto que se esté enumerando se llama al bloque, se le pasa el argumento "n" y el propio objeto. El resultado se vuelve a añadir a "n". Por lo tanto para definir sum, se podría escribir:
	    
	    module Enumerable
	      def sum
	        inject(0) {|n ,i | n + i}
	      end
	    end
	  
	    [1,3,5,7,9].sum      # -> 25
	    [1 .. 100].sum       # -> 5050
	  

P: ¿Cómo se utilizan las "continuaciones"?

R: Las "continuaciones" en Ruby permiten crear un objeto que representa un punto en un programa y su retorno a él en cualquier momento (incluso si aparentemente han salido de ámbito). Se utilizan para implementar estructuras de control complejas pero son sobre todo muy útiles para confundir a las personas.

En [ruby-talk:4482], Jim Weirich publicó los siguientes ejemplos de continuaciones:

	    # ---------------------------------------------
	    # Productor/Consumidor sencillo
	    # ---------------------------------------------
	    # Conecta con una sencilla tarea de conteo y una
	    # tarea de impresión utilizando continuaciones
	    #
	    # Utilización: count(limit)
	    def count_task(count, consumer)
	      (1..count).each do | i |
	        callcc { |cc| consumer.call cc, i }
	      end
	      nil
	    end

	    def print_task()
	      producer i = callcc { |cc| return cc }
	      print "#{i}"
	      callcc { |cc| producer.call }
	    end

	    def count(limit)
	      count_task(limit, print_task())
	      print "\n"
	    end

	    # --------------------------------------------
	    # Filtrado de los múltiplos de un número dado
	    # --------------------------------------------
	    # Crea un filtro que es tanto productor como
	    # consumidor. Se inserta entre las tareas de 
	    # conteo e impresión.
	    #
	    # Utilización: omit(2, limit)

	    def filter_task(factor, consumer)
	      producer, i = callcc {|cc| return cc}
	      if (i%factor) != 0 then 
	        callcc { |cc| consumer.call cc, i }
	      end
	      producer.call
	    end

	    def omit(factor, limit)ç
	      printer = print_task()
	      filter = filter_task(factor, printer)
	      count_task(limit, filter)
	      print "\n"
	    end

	    # ---------------------------------------------
	    # Generador de números primos
	    # ---------------------------------------------
	    # Crea un generador de números primos. Al descu
	    # brir un nuevo primo, añade dinámicamente un 
	    # filtro de múltiplos a la cadena de productores
	    # consumidores
	    # 
	    # Utilización: primes (limit)
	    
	    def prime_task(consumer)
	      producer, i = callcc{ |cc| return cc }
	      if i >= 2 then
	        callcc {|cc| consumer.call cc, i }
		consumer = filter_task(i, consumer)
	      end
	      producer.call
	    end

	    def primes(limit)
	      printer = print_task()
	      primes = prime_task(printer)
	      count_task(limit, primes)
	      print "\n"
	    end