ruby en linux

24
Ruby en Linux Dependiendo de la distribución que utilices, hay varias maneras de instalar Ruby. La primer opción es simplemente bajar el código fuente y compilarlo a mano. Pero en algunas plataformas, hay gestores de paquetes que hacen la instalación de Ruby extremadamente sencilla. Debian/Ubuntu: % sudo apt-get install ruby irb rdoc Archlinux: # pacman -S ruby Gentoo/Sabayon/Funtoo Linux: # emerge ruby Acerca de Ruby ¿Te preguntas por qué Ruby es tan popular? Sus fanáticos lo tienen como un lenguaje hermoso y artístico. Y todavía así, dicen que es práctico y ameno. ¿Por qué? Los ideales del creador de Ruby Ruby es un lenguaje con un balance cuidado. Su creador, Yukihiro ―matz‖ Matsumoto , mezcló partes de sus lenguajes favoritos (Perl, Smalltalk, Eiffel, Ada, y Lisp) para formar un nuevo lenguaje que incorporara tanto la programación funcional como la programación imperativa.

Upload: vilna2011

Post on 27-Jun-2015

501 views

Category:

Education


0 download

TRANSCRIPT

Page 1: Ruby en linux

Ruby en Linux

Dependiendo de la distribución que utilices, hay varias maneras de instalar Ruby. La primer opción es simplemente bajar el código fuente

y compilarlo a mano. Pero en algunas plataformas, hay gestores de

paquetes que hacen la instalación de Ruby extremadamente sencilla.

Debian/Ubuntu:

% sudo apt-get install ruby irb rdoc

Archlinux:

# pacman -S ruby

Gentoo/Sabayon/Funtoo Linux:

# emerge ruby

Acerca de Ruby

¿Te preguntas por qué Ruby es tan popular? Sus fanáticos lo tienen como un lenguaje hermoso y artístico. Y todavía así, dicen que es

práctico y ameno. ¿Por qué?

Los ideales del creador de Ruby

Ruby es un lenguaje con un balance cuidado. Su creador, Yukihiro ―matz‖ Matsumoto, mezcló partes de sus lenguajes favoritos (Perl,

Smalltalk, Eiffel, Ada, y Lisp) para formar un nuevo lenguaje que incorporara tanto la programación funcional como la programación

imperativa.

Page 2: Ruby en linux

A menudo ha manifestado que está ―tratando de hacer que Ruby sea

natural, no simple‖, de una forma que se asemeje a la vida real.

Continuando sobre esto, agrega:

Ruby es simple en apariencia, pero complejo por dentro, como el

cuerpo humano1.

Acerca del crecimiento de Ruby

Desde su liberación pública en 1995, Ruby ha atraído devotos desarrolladores de todo el mundo. En el 2006, Ruby alcanzó

reconocimiento masivo, formándose grupos de usuarios activos en las ciudades más importantes del mundo y llenando las capacidades de

las conferencias relacionadas a Ruby.

Ruby-Talk, la lista de correo más importante sobre el lenguaje Ruby

ha crecido hasta lograr un promedio de 200 mensajes por día.

El índice TIOBE, que mide el crecimiento de los lenguajes de

programación, ubica a Ruby en la posición #13 del ranking mundial. Refiriéndose a su crecimiento, predicen, ―Todo indica que Ruby

llegará a estar entre los 10 primeros en menos de 6 meses‖. Gran parte de su crecimiento se atribuye a la popularidad alcanzada por

aplicaciones desarrolladas con Ruby, en particular el framework de desarrollo web Ruby on Rails2.

Ruby es totalmente libre. No sólo gratis, sino también libre para usarlo, copiarlo, modificarlo y distribuirlo.

Viendo todo como un objeto

Inicialmente, Matz buscó en otros lenguajes para encontrar la sintaxis ideal. Recordando su búsqueda, dijo, ―quería un lenguaje que fuera

más poderoso que Perl, y más orientado a objetos que Python3‖.

En Ruby, todo es un objeto. Se le puede asignar propiedades y

acciones a toda información y código. La programación orientada a objetos llama a las propiedades variables de instancia y las acciones

son conocidas como métodos. La orientación a objetos pura de Ruby

Page 3: Ruby en linux

se suele demostrar con un simple código que aplica una acción a un

número.

5.times { print "Nos *encanta* Ruby -- ¡es fuera de serie!" }

En muchos lenguajes, los números y otros tipos primitivos no son objetos. Ruby sigue la influencia del lenguaje Smalltalk pudiendo poner métodos y variables de instancia a todos sus tipos de datos.

Esto facilita el uso de Ruby, porque las reglas que se aplican a los objetos son aplicables a todo Ruby.

La flexibilidad de Ruby

Ruby es considerado un lenguaje flexible, ya que permite a sus

usuarios alterarlo libremente. Las partes esenciales de Ruby pueden ser quitadas o redefinidas a placer. Se puede agregar funcionalidad a

partes ya existentes. Ruby intenta no restringir al desarrollador.

Por ejemplo, la suma se realiza con el operador suma (+). Pero si

prefieres usar la palabra sumar, puedes agregar un método llamado

sumar a la clase Numeric que viene incorporada.

class Numeric

def sumar(x)

self.+(x)

end

end

y = 5.sumar 6

# ahora y vale 11

Los operadores de Ruby son simples conveniencias sintácticas para

los métodos. Los puedes redefinir como y cuando quieras.

Los Bloques, una funcionalidad realmente expresiva

Los bloques de Ruby son también vistos como una fuente de gran

flexibilidad. El desarrollador puede anexar una cláusula a cualquier método, describiendo cómo debe actuar. La cláusula es llamada

bloque y se ha convertido en una de las más famosas funcionalidades para los recién llegados a Ruby que vienen de otros lenguajes

imperativos como PHP o Visual Basic.

Los bloques están inspirados por los lenguajes funcionales. Matz dijo,

―en las cláusulas de Ruby, quise respetar la cultura de Lisp4‖.

motores_de_busqueda =

%w[Google Yahoo MSN].map do |motor|

"http://www." + motor.downcase + ".com"

end

Page 4: Ruby en linux

En este código, el bloque está descrito entre la construcción do ...

end. El método map aplica el bloque a la lista de palabras provista.

Muchos otros métodos en Ruby dejan abierta la posibilidad al desarrollador para que escriba su propio bloque describiendo los

detalles de qué debe hacer ese método.

Ruby y el Mixin

A diferencia de otros lenguajes de programación orientada a objetos,

Ruby se caracteriza por su intencional herencia simple. Sin embargo, Ruby incorpora el concepto de módulos (llamados categorías en

Objective-C), que son colecciones de métodos.

Las clases pueden mezclar (mixin) un módulo e incorporar todos sus

métodos gratuitamente. Por ejemplo, cualquier clase que implemente

el método each puede incorporar el módulo Enumerable, que le agrega

un conjunto de métodos que usan each para recorrer sus elementos.

class MiArray

include Enumerable

end

En general, los Rubyistas ven esto como una forma mucho más clara de herencia múltiple, que es compleja e incluso puede ser restrictiva.

La apariencia visual de Ruby

A pesar de que Ruby utiliza la puntuación muy limitadamente y se

prefieren las palabras clave en inglés, se utiliza algo de puntuación para decorar el código. Ruby no necesita declaraciones de variables.

Se utilizan convenciones simples para nombrar y determinar el alcance de las mismas.

var puede ser una variable local.

@var es una variable de instancia.

$var es una variable global.

Estos detalles mejoran la legibilidad permitiendo que el desarrollador identifique fácilmente los roles de las variables. También se hace

innecesario el uso del molesto self. como prefijo de todos los

miembros de instancia.

Más allá de lo básico

Ruby tiene un conjunto de otras funcionalidades entre las que se encuentran las siguientes:

manejo de excepciones, como Java y Python, para facilitar el manejo de errores.

Page 5: Ruby en linux

un verdadero mark-and-sweep garbage collector para todos los

objetos de Ruby. No es necesario mantener contadores de referencias en bibliotecas externas. Como dice Matz, ―Esto es mejor para tu

salud‖.

escribir extenciones en C para Ruby es más fácil que hacer lo mismo para Perl o Python, con una API muy elegante para utilizar Ruby

desde C. Esto incluye llamadas para embeber Ruby en otros programas, y así usarlo como lenguaje de scripting. También está disponible una interfaz SWIG.

puede cargar bibliotecas de extensión dinámicamente si lo permite el

sistema operativo.

tiene manejo de hilos (threading) independiente del sistema operativo. De esta forma, tienes soporte multi-hilo en todas las

plataformas en las que corre Ruby, sin importar si el sistema operativo lo soporta o no, ¡incluso en MS-DOS!

Ruby es fácilmente portable: se desarrolla mayoritariamente en

GNU/Linux, pero corre en varios tipos de UNIX, Mac OS X, Windows 95/98/Me/NT/2000/XP, DOS, BeOS, OS/2, etc.

Referencias

1 Matz, hablando en la lista de correo Ruby-Talk, 12 de mayo del 2000.

2 Mira la página de Ruby on Rails para averiguar más.

3 Matz, en An Interview with the Creator of Ruby, 29 de noviembre

del 2001.

4 Matz, en Blocks and Closures in Ruby, 22 de diciembre del 2003.

Ruby en 20 minutos

Introducción

Este es un pequeño tutorial de Ruby que no debería tomar más de 20

minutos completarlo. Se asume que ya tienes instalado Ruby. Si no tienes Ruby funcionando en tu PC, descárgalo e instálalo antes de

comenzar.

Ruby interactivo

Arranca el IRB.

Page 6: Ruby en linux

Si estás usando Mac OS X abre una Terminal y escribe irb, después

presiona enter.

Si estás usando Linux, abre una Terminal y escribe irb, después

presiona enter.

Si estás usando Windows, abre fxri desde la sección Ruby de tu

Menú de Inicio.

irb(main):001:0>

Bien, ahora está abierto. ¿Y ahora qué?

Escribe esto: "Hola Mundo"

irb(main):001:0> "Hola Mundo"

=> "Hola Mundo"

¡Ruby te obedeció!

¿Qué fue lo que pasó? ¿Acaso acabamos de escribir el programa

―Hola Mundo‖ más corto del mundo? No exactamente. La segunda linea sólo es la forma que tiene IRB para decirnos el resultado de la

última expresión evaluada. Si queremos que el programa escriba ―Hola Mundo‖ necesitamos un poco más:

irb(main):002:0> puts "Hola Mundo"

Hola Mundo

=> nil

puts es el comando básico para escribir algo en Ruby. Pero entonces,

¿qué es ese => nil? Ese es el resultado de la expresión. puts siempre

retorna nil, que es el valor que significa ―absolutamente nada‖ en

Ruby.

Tu calculadora gratis está aquí

Pronto, tenemos suficiente para usar IRB como una calculadora

básica:

irb(main):003:0> 3+2

=> 5

Tres más dos. Bastante fácil. ¿Y qué tal tres veces dos? Podrías escribirlo, es bastante corto, pero también podrías subir y simplemente cambiar lo que ya ingresaste. Prueba presionando la

flecha hacia arriba en tu teclado y verifica si aparece la linea con

3+2 escrito. Si es así, puedes usar la flecha hacia la izquierda para

posicionarte junto al signo + y cambiarlo por un *.

irb(main):004:0> 3*2

=> 6

Page 7: Ruby en linux

Ahora intentemos tres al cuadrado:

irb(main):005:0> 3**2

=> 9

En Ruby ** es la forma que tienes para decir ―elevado al‖. ¿Y qué tal

si quieres hacer lo inverso y encontrar la raíz cuadrada de algo?

irb(main):006:0> Math.sqrt(9)

=> 3.0

Bien, esperen, ¿qué fue eso? Si adivinaste, ―fue la forma de averiguar la raíz cuadrada de nueve‖, estás en lo cierto. Pero veamos las cosas

un poco más de cerca. Antes que nada, ¿qué es Math?

Módulos, agrupa el código por tópicos

Math es un módulo incluido para matemáticas. Los módulos tienen dos

roles en Ruby. Esto muestra uno de sus roles: agrupar métodos

similares bajo un nombre familiar. Math también tiene métodos como

sin() y tan().

Después de Math hay un punto. ¿Cuál es la función del punto? El

punto es la forma de identificar al receptor de un mensaje. ¿Qué es

un mensaje? En este caso es sqrt(9), que significa ―llama al método

sqrt‖, abreviación de ―square root‖ (raíz cuadrada) con el parámetro

9.

El resultado de la llamada a este método es el valor 3.0. Notarás que

no es simplemente 3. Eso es porque la mayoría de las veces la raíz

cuadrada de un número no será un número entero, así que el método

siempre retorna un número flotante.

¿Y qué pasa si queremos recordar el resultado de algunas de estas operaciones? Asigna el resultado a una variable.

irb(main):007:0> a = 3 ** 2

=> 9

irb(main):008:0> b = 4 ** 2

=> 16

irb(main):009:0> Math.sqrt(a+b)

=> 5.0

Por más bueno que esté esto de la calculadora, nos estamos alejando

del tradicional mensaje Hola Mundo en el que se supone que los cursos

para principiantes deben enfocarse… así que volvamos a eso.

¿Qué tal si queremos decir ―Hola‖ muchas veces sin cansar nuestros dedos con el teclado? ¡Necesitamos definir un método!

Page 8: Ruby en linux

irb(main):010:0> def h

irb(main):011:1> puts "Hola Mundo"

irb(main):012:1> end

=> nil

La expresión def h inicia la definición del método. Le dice a Ruby que

estamos definiendo un método, cuyo nombre es h. La siguiente linea

es el cuerpo del método, la misma expresión que vimos

anteriormente: puts "Hola Mundo". Finalmente, la última linea end la

dice a Ruby que terminamos de definir el método. La respuesta de

Ruby => nil nos comunica que él sabe que terminamos de definir el

método.

Las breves y repetitivas vidas de un método

Ahora intentemos ejecutar ese método algunas veces:

irb(main):013:0> h

Hola Mundo

=> nil

irb(main):014:0> h()

Hola Mundo

=> nil

Bien, eso fue fácil. Ejecutar un método en Ruby es tan fácil como sólo mencionar su nombre. Si el método no requiere parámetros para ejecutarse, eso es todo lo que necesitas. Puedes agregar paréntesis

vacíos, pero no son necesarios.

¿Y qué tal si queremos saludar sólo a una persona y no a todo el

mundo? Simplemente redefine h para que tome un nombre como

parámetro.

irb(main):015:0> def h(nombre)

irb(main):016:1> puts "Hola #{nombre}"

irb(main):017:1> end

=> nil

irb(main):018:0> h("Matz")

Hola Matz

=> nil

Así que eso funciona… pero tomémonos un segundo para ver más en

detalle qué es lo que está sucediendo.

Reservando espacios en un String

¿Qué significa la expresión #{nombre}? Esa es la forma que tiene Ruby

para insertar algo en un String. La expresión entre las llaves es

transformada en un String (si todavía no lo es) y posteriormente sustituida en ese punto del String que la contiene. También puedes

usar esto para asegurarte que el nombre comience con mayúscula:

Page 9: Ruby en linux

irb(main):019:0> def h(nombre = "Mundo")

irb(main):020:1> puts "Hola #{nombre.capitalize}"

irb(main):021:1> end

=> nil

irb(main):022:0> h "pedro"

Hola Pedro

=> nil

irb(main):023:0> h

Hola Mundo

=> nil

Algunos otros trucos para destacar. Uno es que otra vez estamos

llamando al método sin utilizar los paréntesis. Si lo que quieres hacer es obvio, los paréntesis son opcionales. El otro truco es el parámetro

por defecto Mundo. Esto significa ―si no se provee un nombre, utiliza el

nombre por defecto "Mundo"‖.

Convirtiéndolo en un Anfitrión

¿Qué hacemos si queremos tener un anfitrión más ―en serio‖? Uno que recuerde tu nombre, te dé la bienvenida y te trate con respeto.

Puedes querer utilizar un objeto para eso. Vamos a crear la clase ―Anfitrion‖.

irb(main):024:0> class Anfitrion

irb(main):025:1> def initialize(nombre = "Mundo")

irb(main):026:2> @nombre = nombre

irb(main):027:2> end

irb(main):028:1> def decir_hola

irb(main):029:2> puts "Hola #{@nombre}"

irb(main):030:2> end

irb(main):031:1> def decir_adios

irb(main):032:2> puts "Adiós #{@nombre}, vuelve pronto."

irb(main):033:2> end

irb(main):034:1> end

=> nil

La nueva palabra clave aquí es class. Esto define una nueva clase

llamada Anfitrion y un par de métodos para esa clase. También toma

nota de @nombre. Esta es una variable de instancia y está disponible

para todos los métodos de la clase. Como puedes ver es utilizada por

decir_hola y decir_adios.

¿Así que cómo hacemos para que esta clase Anfitrion nos sea de

utilidad? Crea un objeto.

Ahora vamos a crear y usar un objeto anfitrión:

irb(main):035:0> a = Anfitrion.new("Juan")

=> #<Anfitrion:0x16cac @nombre="Juan">

irb(main):036:0> a.decir_hola

Hola Juan

=> nil

irb(main):037:0> a.decir_adios

Page 10: Ruby en linux

Adiós Juan, vuelve pronto.

=> nil

Una vez que el objeto a es creado, nos recuerda que el nombre es

Juan. Mmm, ¿y si queremos acceder al nombre directamente?

irb(main):038:0> a.@nombre

SyntaxError: compile error

(irb):52: syntax error

from (irb):52

No, no podemos.

Por debajo de la piel del objeto

Las variables de instancia se esconden dentro del objeto. No están

tan escondidas, las puedes ver cuando inspeccionas el objeto, y hay otras formas de acceder a ellas, pero Ruby es fiel a las buenas

costumbres de la programación orientada a objetos manteniendo los datos lo más privados posible.

Entonces, ¿qué métodos están disponibles para los objetos Anfitrion?

irb(main):039:0> Anfitrion.instance_methods

=> ["method", "send", "object_id", "singleton_methods",

"__send__", "equal?", "taint", "frozen?",

"instance_variable_get", "kind_of?", "to_a",

"instance_eval", "type", "protected_methods", "extend",

"eql?", "display", "instance_variable_set", "hash",

"is_a?", "to_s", "class", "tainted?", "private_methods",

"untaint", "decir_hola", "id", "inspect", "==", "===",

"clone", "public_methods", "respond_to?", "freeze",

"decir_adios", "__id__", "=~", "methods", "nil?", "dup",

"instance_variables", "instance_of?"]

Bien. Eso es un montón de métodos. Nosotros sólo definimos dos métodos. ¿Qué es lo que está sucediendo? Bueno, estos son todos

los métodos para los objetos Anfitrion, una lista completa, incluyendo los que están definidos en las superclases de Anfitrion. Si queremos

listar únicamente los métodos definidos para la clase Anfitrion podemos pedirle que no incluya sus ancestros pasándole el

parámetro false, que significa que no queremos los métodos

definidos por sus ancestros.

irb(main):040:0> Anfitrion.instance_methods(false)

=> ["decir_adios", "decir_hola"]

Ah, hay más cosas como esa. Veamos a qué métodos puede

responder nuestro objeto anfitrión:

irb(main):041:0> a.respond_to?("nombre")

=> false

irb(main):042:0> a.respond_to?("decir_hola")

Page 11: Ruby en linux

=> true

irb(main):043:0> a.respond_to?("to_s")

=> true

Así que, sabe decir_hola, y to_s (que significa ―convertir algo en un

string‖, un método que está definido por defecto para todos los

objetos), pero no reconoce nombre como un método.

Modificando clases—Nunca es demasiado tarde

¿Pero qué pasa si quieres poder ver o modificar el nombre? Ruby provee una forma fácil para permitir acceder a las variables de un

objeto.

irb(main):044:0> class Anfitrion

irb(main):045:1> attr_accessor :nombre

irb(main):046:1> end

=> nil

En Ruby, puedes volver a abrir una clase y modificarla. Eso no

cambia objetos que ya existan, pero afecta a los nuevos objetos que puedas crear. Así que vamos a crear un nuevo objeto y juguemos con

su propiedad @nombre.

irb(main):047:0> a = Anfitrion.new("Pedro")

=> #<Anfitrion:0x3c9b0 @nombre="Pedro">

irb(main):048:0> a.respond_to?("nombre")

=> true

irb(main):049:0> a.respond_to?("nombre=")

=> true

irb(main):050:0> a.decir_hola

Hola Pedro

=> nil

irb(main):051:0> a.nombre="Matilde"

=> "Matilde"

irb(main):052:0> a

=> #<Anfitrion:0x3c9b0 @nombre="Matilde">

irb(main):053:0> a.nombre

=> "Matilde"

irb(main):054:0> a.decir_hola

Hola Matilde

=> nil

El uso de attr_accessor determinó que se definan dos nuevos métodos

por nosotros, nombre para obtener el valor, y nombre= para modificarlo.

Saludando a todo el mundo, ¡MegaAnfitrion no niega el saludo a

nadie!

De todas formas, este anfitrión no es tan interesante, sólo puede trabajar con una persona a la vez. ¿Qué pasaría si tuviéramos alguna

Page 12: Ruby en linux

clase MegaAnfitrion que pudiera saludar al mundo, a una persona, o

una lista completa de personas?

Escribamos esto en un archivo en vez de usar directamente el

intérprete interactivo de Ruby IRB.

Para salir de IRB, escribe ―quit‖, ―exit‖ o simplemente presiona Control-D.

#!/usr/bin/env ruby

class MegaAnfitrion

attr_accessor :nombres

# Crear el objeto

def initialize(nombres = "Mundo")

@nombres = nombres

end

# Decirle hola a todos

def decir_hola

if @nombres.nil?

puts "..."

elsif @nombres.respond_to?("each")

# @nombres es una lista de algún tipo,

# ¡así que podemos iterar!

@nombres.each do |nombre|

puts "Hola #{nombre}"

end

else

puts "Hola #{@nombres}"

end

end

# Decirle adiós a todos

def decir_adios

if @nombres.nil?

puts "..."

elsif @nombres.respond_to?("join")

# Juntar los elementos de la lista

# usando la coma como separador

puts "Adiós #{@nombres.join(", ")}. Vuelvan pronto."

else

puts "Adiós #{@nombres}. Vuelve pronto."

end

end

end

if __FILE__ == $0

ma = MegaAnfitrion.new

ma.decir_hola

ma.decir_adios

# Cambiar el nombre a "Diego"

ma.nombres = "Diego"

ma.decir_hola

Page 13: Ruby en linux

ma.decir_adios

# Cambiar el nombre a un vector de nombres

ma.nombres = ["Alberto", "Beatriz", "Carlos",

"David", "Ernesto"]

ma.decir_hola

ma.decir_adios

# Cambiarlo a nil

ma.nombres = nil

ma.decir_hola

ma.decir_adios

end

Guarda este archivo como ―ri20min.rb‖, y ejecútalo con ―ruby ri20min.rb‖. El resultado debería ser:

Hola Mundo

Adiós Mundo. Vuelve pronto.

Hola Diego

Adiós Diego. Vuelve pronto.

Hola Alberto

Hola Beatriz

Hola Carlos

Hola David

Hola Ernesto

Adiós Alberto, Beatriz, Carlos, David, Ernesto. Vuelvan pronto.

...

...

Hay un montón de cosas nuevas en este nuevo ejemplo en las que podemos echar una mirada más profunda.

Así que, investigando nuestro programa, notarás que las primeras

lineas comienzan con un numeral (#). En Ruby, todo lo que esté detrás de un numeral es un comentario y es ignorado por el

intérprete. La primer linea del archivo es un caso especial y en los sistemas operativos del estilo Unix determina cómo ejecutar el

archivo. El resto de los comentarios están únicamente para aportar claridad al significado del código.

Nuestro método decir_hola se ha vuelto un poco más complicado:

# Decirle hola a todos

def decir_hola

if @nombres.nil?

puts "..."

elsif @nombres.respond_to?("each")

# @nombres es una lista de algún tipo,

# ¡así que podemos iterar!

@nombres.each do |nombre|

puts "Hola #{nombre}"

end

else

puts "Hola #{@nombres}"

Page 14: Ruby en linux

end

end

Ahora usa el atributo @nombres para tomar decisiones. Si es nil, sólo

imprime tres puntos. No hay razón para saludar a nadie, ¿cierto?

Iterando

Si el objeto @nombres responde al método each, es algo sobre lo que se

puede iterar, así que iteramos entre sus elementos y saludamos a

cada uno de sus integrantes. Finalmente, si @nombres es otra cosa,

dejamos que automáticamente se convierta en un string y usamos el

saludo por defecto.

Veamos ese iterador en más detalle:

@nombres.each do |nombre|

puts "Hola #{nombre}"

end

El método each acepta un bloque de código y lo ejecuta por cada

elemento de la lista, y el código entre do y end es el bloque en sí

mismo. Un bloque es como una función anónima o lambda. La variable

entre los pipes (|) es el parámetro para este bloque.

Lo que sucede es que por cada elemento en la lista, nombre va

tomando su valor y se ejecuta la expresión puts "Hola #{nombre}" con

ese nombre.

Muchos otros lenguajes de programación manejan la iteración de una

lista usando la clásica sintaxis for, que en C se ve así:

for (i=0; i<cantidad_de_elementos; i++)

{

hacer_algo_con(elementos[i]);

}

Esto funciona, pero no es muy elegante. Necesitas una variable

descartable como i, averiguar la cantidad de elementos de la lista, y

explicar cómo recorrerla. La costumbre Ruby (The Ruby Way) es

mucho más elegante, todos los detalles de infraestructura se ocultan

en el método each, todo lo que necesitas hacer es decirle qué hacer

con cada elemento. Internamente, el método each llamará yield

"Alberto", después yield "Beatriz", después yield "Carlos", y así

sucesivamente.

Page 15: Ruby en linux

Los bloques, una de las funcionalidades más potentes de Ruby

El poder real de los bloques se disfruta al trabajar con cosas más complicadas que las listas. Más allá de manejar los detalles de infraestructura dentro del método, también puedes manejar la

inicialización, la finalización, y los errores—todos ocultos y

simplificados frente a las preocupaciones del desarrollador.

# Decirle adiós a todos

def decir_adios

if @nombres.nil?

puts "..."

elsif @nombres.respond_to?("join")

# Juntar los elementos de la lista

# usando la coma como separador

puts "Adiós #{@nombres.join(", ")}. Vuelvan pronto."

else

puts "Adiós #{@nombres}. Vuelve pronto."

end

end

El método decir_adios no usa each, en vez de eso se fija si @nombres

responde al método join, y si es así, lo usa. Si no es así, simplemente

imprime la variable como un string. Esta práctica de no preocuparse

sobre el tipo de objeto de una variable, y simplemente depender de los métodos que esta soporta, es conocida como ―Duck Typing‖. El

beneficio es que no limita innecesariamente los tipos de variables que son soportados. Si alguien inventa un nuevo tipo de lista, siempre y

cuando implemente el método join con la misma semántica que otras

listas, todo funcionará como fue planeado.

Arrancando el Script

Así que eso es la clase MegaAnfitrion, el resto del archivo sólo llama a los métodos de la clase. Hy un último truco para tener en cuenta, y

es la linea:

if __FILE__ == $0

__FILE__ es la variable mágica que contiene el nombre del archivo que

se está ejecutando en ese momento. $0 es el nombre del archivo

usado para iniciar el programa. Esta verificación dice ―si este es el

archivo principal…‖. Esto permite que un archivo sea utilizado como una biblioteca, y no ejecutar código en ese contexto. Pero si el

archivo está siendo usado como un ejecutable, entonces ejecuta ese código.

Page 16: Ruby en linux

Considérate iniciado

Eso es todo en este rápido paseo por Ruby. Hay mucho más por explorar, las estructuras de control diferentes que ofrece Ruby; el uso

e los bloques y yield; módulos como mixins; y más. Espero que esta

pequeña muestra de Ruby te despierte el interés por saber más.

Si es así, por favor dirígete a nuestra area de Documentación, donde

encontrarás vínculos a cursos y manuales, todos disponibles gratuitamente en internet.

O si realmente te gustaría sumergirte en un libro, busca en el listado

de libros los títulos disponibles para venta en linea o en tu tienda

favorita.

Ruby desde otros lenguajes

Cuando te enfrentas por primera vez a código escrito en Ruby,

probablemente te recuerde otros lenguajes que hayas usado. Esto es a propósito. La mayor parte de la sintaxis es familiar para los

usuarios de Perl, Python, y Java (entre otros lenguajes), así que si has usado alguno de estos, aprender Ruby será muy fácil.

Este documento contiene dos secciones. La primera intenta ser un

resumen de lo que puedes esperar ver al aprender Ruby viniendo de

otro lenguaje. La segunda sección se enfoca en determinadas funcionalidades del lenguaje y cómo podrían compararse a lo que ya

puedas estar familiarizado.

Qué esperar: Lenguaje X a Ruby

A Ruby desde Java A Ruby desde PHP

Estamos en proceso de traducir todos estos artículos, pero mientras

lo hacemos no queremos privarte de que los leas en inglés:

To Ruby From C and C++ (en inglés) To Ruby From Java (en inglés)

To Ruby From Perl (en inglés) To Ruby From PHP (en inglés)

To Ruby From Python (en inglés)

Funcionalidades importantes del lenguaje y algunas advertencias

Aquí tienes algunas referencias y consejos sobre funcionalidades de Ruby que verás mientras lo aprendes.

Page 17: Ruby en linux

Iteración

Dos funcionalidades de Ruby que se diferencian de lo que puedes haber visto previamente, y que toma cierto tiempo acostumbrarse a

ellas, son los ―bloques‖ e iteradores. En vez de recorrer un índice

(como con C, C++, o Java anterior al 1.5), o recorrer una lista (como

el for (@a) {...} de Perl, o for i in aList: ... en Python, con Ruby

verás muy frecuentemente código de este estilo:

una_lista.each do |este_item|

# Estamos dentro del bloque.

# Trabaja con este_item.

end

Para obtener más información sobre each (y sus amigos collect, find,

inject, sort, etc.), ejecuta ri Enumerable (y después ri

Enumerable#nombre_del_metodo).

Todo tiene un valor

No hay diferencia entre una expresión y un comando. Todo tiene un valor, incluso si ese valor es nil. Esto es posible:

x = 10

y = 11

z = if x < y

true

else

false

end

z # => true

Los symbols (símbolos) no son strings especiales

A muchos novatos en Ruby les cuesta entender qué son los symbols,

y qué utilidad pueden tener.

Los symbols pueden ser descritos como identidades. Lo importante de

un Symbol es quién es, no qué es. Arranca irb y experimenta la

diferencia:

irb(main):001:0> :jorge.object_id == :jorge.object_id

=> true

irb(main):002:0> "jorge".object_id == "jorge".object_id

=> false

irb(main):003:0>

El método object_id retorna la identidad de un objeto. Si dos objetos

tienen el mismo object_id, son el mismo objeto (apuntan al mismo

objeto en la memoria).

Page 18: Ruby en linux

Como puedes ver, una vez que has usado un Symbol, cualquier otro

Symbol con los mismos caracteres referencia al mismo objeto en memoria. Para dos symbols que representan los mismos caracteres,

el object_id es el mismo.

Ahora veamos el String (―jorge‖). El object_id no es el mismo. Eso

significa que representan a dos objetos diferentes en memoria. Siempre que uses un nuevo String, Ruby reserva memoria para él.

Si tienes dudas sobre usar un Symbol o un String, considera qué es más importante: la identidad de un objeto (por ejemplo la Key de un

Hash), o el contenido (en nuestro ejemplo, ―jorge‖).

Todo es un objeto

―Todo es un objeto‖ no es una exageración. Incluso las clases y los

enteros son objetos, y puedes hacer con ellos las mismas cosas que con cualquier otro objeto:

# Esto es lo mismo que:

# class MiClase

# attr_accessor :variable_de_instancia

# end

MiClase = Class.new do

attr_accessor :variable_de_instancia

end

Constantes variables

Las constantes no son realmente… constantes. Si modificas una constante previamente inicializada, Ruby disparará una advertencia,

pero no detendrá tu programa. De todas formas, eso no quiere decir que deberías redefinir tus constantes.

Convenciones de sintaxis

Ruby impone algunas convenciones de sintaxis. Si un identificador comienza con una letra mayúscula, es una constante. Si comienza

con un símbolo de moneda ($), es una variable global. Si comienza

con @, es una variable de instancia. Si comienza con @@, es una

variable de clase.

Sin embargo, los nombres de los métodos tienen permitido comenzar

con letras mayúsculas. Esto puede confundirte, como muestra el siguiente ejemplo:

Constante = 10

def Constante

11

end

Page 19: Ruby en linux

Ahora Constante vale 10, pero Constante() retorna 11.

Falsos parámetros nombrados

A diferencia de Python, Ruby no tiene parámetros nombrados. Sin

embargo, pueden ser emulados mediante el uso de symbols y hashes. Ruby on Rails, entre otros, usa esto a discreción. Por

ejemplo:

def parametros_con_nombre( params )

params

end

parametros_con_nombre( :param_uno => 10, :param_dos => 42 )

# => {:param_uno=>10, :param_dos=>42}

La verdad universal

En Ruby, todo excepto nil y false es considerado true. En C, Python

y muchos otros lenguajes, 0* y posiblemente otros valores, como listas vacías, son considerados *false. Examina el siguiente

código Python (el ejemplo aplica también a otros lenguajes):

# en Python

if 0:

print "0 es verdadero"

else:

print "0 es falso"

Esto imprimirá ―0 es falso‖. El equivalente en Ruby:

# en Ruby

if 0

puts "0 es verdadero"

else

puts "0 es falso"

end

Imprime ―0 es verdadero‖.

Los modificadores de acceso aplican hasta el fin del alcance

En el siguiente código Ruby,

class MiClase

private

def un_metodo; true; end

def otro_metodo; false; end

end

Puede ser que esperes que otro_metodo sea de alcance público. Esto

no es así. El modificador de acceso ‗private‘ continúa hasta el fin del

Page 20: Ruby en linux

alcance, o hasta que aparezca un nuevo modificador de acceso, lo

que ocurra primero. Por defecto, los métodos son públicos:

class MiClase

# Ahora un_metodo es público

def un_metodo; true; end

private

# otro_metodo es privado

def otro_metodo; false; end

end

public, private y protected en realidad son métodos, así que pueden recibir

parámetros. Si pasas un símbolo a uno de ellos, la visibilidad de ese método

es alterada.

Acceso a los métodos

En Java, public significa que un método puede ser accedido por

cualquiera. protected significa que las instancias de la clase,

instancias de sus descendientes así como también de clases en el

mismo paquete, pueden accederlo, pero nadie más. Y private significa

que los métodos son accesibles únicamente desde las instancias de la

clase.

En Ruby esto es un poco diferente. public es, naturalmente, público.

private significa que los métodos son accesibles sólo cuando pueden

ser invocados sin un receptor explícito. Sólo self tiene permitido ser

el receptor de la invocación a un método privado.

Al que debemos estar atentos es a protected. Un método protegido

puede ser llamado desde una instancia de una clase o las instancias

de sus ancestros, pero también con otra instancia como su receptor.

Ejemplo, adaptado del Ruby FAQ:

$ irb

irb(main):001:0> class Test

irb(main):002:1> # public por defecto

irb(main):003:1* def func

irb(main):004:2> 99

irb(main):005:2> end

irb(main):006:1>

irb(main):007:1* def ==(otro)

irb(main):008:2> func == otro.func

irb(main):009:2> end

irb(main):010:1> end

=> nil

irb(main):011:0>

irb(main):012:0* t1 = Test.new

=> #<Test:0x34ab50>

irb(main):013:0> t2 = Test.new

=> #<Test:0x342784>

Page 21: Ruby en linux

irb(main):014:0> t1 == t2

=> true

irb(main):015:0> # ahora haz 'func' protected, todavía funciona

irb(main):016:0* # porque protected permite la otra referencia

irb(main):017:0* class Test

irb(main):018:1> protected :func

irb(main):019:1> end

=> Test

irb(main):020:0> t1 == t2

=> true

irb(main):021:0> # ahora haz 'func' private

irb(main):022:0* class Test

irb(main):023:1> private :func

irb(main):024:1> end

=> Test

irb(main):025:0> t1 == t2

NoMethodError: private method `func' called for #<Test:0x342784>

from (irb):8:in `=='

from (irb):25

from :0

irb(main):026:0>

Las clases están abiertas

Las clases de Ruby están abiertas.Puedes abrirlas, agregarles

funcionalidad, y modificarlas en cualquier momento. Incluso las

clases principales, como Fixnum o incluso Object, el padre de todos los

objetos. Ruby on Rails define un montón de métodos para menejar el

tiempo y los horarios en Fixnum. Mira:

class Fixnum

def hours

self * 3600 # cantidad de segundos en una hora

end

alias hour hours

end

# 14 horas desde las 00:00 del 1ro de enero del 2006

Time.mktime(2006, 01, 01) + 14.hours # => Sun Jan 01 14:00:00

Nombres de métodos graciosos

En Ruby, los métodos tienen permitido terminar en signos de

exclamación o interrogación. Por convención, los métodos que

responden preguntas (i.e. Array#empty? retorna true si el receptor

está vacío) terminan con un signo de interrogación. Métodos potencialmente ―peligrosos‖ (i.e. métodos que modifican self o sus

argumentos, exit! etc.) por convención terminan en un signo de

exclamación.

De todas formas, no todos los métodos que modifican sus

argumentos terminan en signos de exclamación. Array#replace

reemplaza el contenido de un array co nel contenido de otro array.

Page 22: Ruby en linux

No tiene mucho sentido tener un método como ese que no modifique

self.

Los métodos Singleton

Los métodos Singleton son métodos-por-objeto. Sólo están disponibles en el objeto en el que los defines.

class Automovil

def inspect

"Auto barato"

end

end

porsche = Automovil.new

porsche.inspect # => Auto barato

def porsche.inspect

"Auto muy caro"

end

porsche.inspect # => Auto muy caro

# Otros objetos no son afectados

otro_auto = Automovil.new

otro_auto.inspect # => Auto barato

Métodos faltantes

Ruby no se rinde si no puede encontrar un método que responda a un

mensaje en particular. Llama al método method_missing con el nómbre

del método que no pudo encontrar y sus argumentos. Por defecto,

method_missing lanza una excepción NameError, pero puedes

redefinirlo para que se ajuste mejor a tu aplicación, y muchas bibliotecas lo hacen. Aquí tienes un ejemplo:

# id es el nombre del método invocado, la sintaxis * recolecta

# todos los argumentos en un array llamado 'argumentos'

def method_missing( id, *argumentos )

puts "El método #{id} fue invocado, pero no existe. Tiene" +

"estos argumentos: #{argumentos.join(", ")}"

end

__ :a, :b, 10

# => El método __ fue invocado, pero no existe. Tiene estos

# argumentos: a, b, 10

Este código sólo imprime los detalles de la invocación, pero eres libre de manejar el mensaje como te parezca más apropiado.

Pasaje de mensajes, no llamadas a funciones

Una invocación a un método en realidad es un mensaje a otro

objeto:

Page 23: Ruby en linux

# Esto

1 + 2

# Es lo mismo que esto ...

1.+(2)

# Que es lo mismo que esto:

1.send "+", 2

Los bloques son objetos, sólo que todavía no lo saben

Los bloques (cierres en realidad) son muy utilizados por la biblioteca

estandar. Para llamar a un bloque, puedes usar yield, o transformarlo

en un Proc al anexarle un parámetro especial a la lista de

argumentos, así:

def block( &el_bloque )

# Aquí dentro, el_bloque es el bloque pasado al método

el_bloque # retornar el bloque

end

sumador = block { |a, b| a + b }

# sumador ahora es un objeto Proc

sumador.class # => Proc

También puedes crear bloques fuera de las invocaciones a métodos,

utilizando Proc.new con un bloque o llamando al método lambda.

Similarmente, los métodos también pueden ser objetos:

method(:puts).call "¡puts es un objeto!"

# => ¡puts es un objeto!

Los operadores son comodidades sintácticas

La mayoría de los operadores en Ruby son simples simplificaciones

sintácticas (con algunas reglas de precedencia) para llamar a ciertos

métodos. Puedes, por ejemplo, redefinir el método Fixnum#+:

class Fixnum

# Puedes, pero por favor no lo hagas

def +( otro )

self - otro

end

end

No necesitas eloperator+ de C++, etc.

Incluso puedes tener acceso estilo array si defines los métodos [] y

[]=. Para definir los métodos unarios + y – (piensa en +1 y -2),

debes definir los métodos +@ and -@ respectivamente.

Sin embargo, los siguientes operadores no son simplificaciones

sintácticas. No son métodos, y no pueden ser redefinidos:

=, .., ..., !, not, &&, and, ||, or, !=, !~, ::

Page 24: Ruby en linux

Además, +=, *= etc. sólo son abreviaciones para var = var + otra_var, var

= var * otra_var, etc. y por ende no pueden ser redefinidos.

Para saber más

Cuando estés listo para saber más sobre Ruby, visita nuestra sección

de Documentación.

Ruby es…

Un lenguaje de programación dinámico y de código abierto enfocado en la simplicidad y productividad. Su elegante sintaxis se siente natural al leerla y fácil al escribirla.

Leer más…

# Output "I love Ruby"

say = "I love Ruby"

puts say

# Output "I *LOVE* RUBY"

say['love'] = "*love*"

puts say.upcase

# Output "I *love* Ruby"

# five times

5.times { puts say }