ruby en 20 minutos

12
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. 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.

Upload: carlosweb2011

Post on 27-Jun-2015

312 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Ruby en 20 minutos

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.

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.

Page 2: Ruby en 20 minutos

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

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

Page 3: Ruby en 20 minutos

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!

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

Page 4: Ruby en 20 minutos

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:

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”.

Page 5: Ruby en 20 minutos

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

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

Page 6: Ruby en 20 minutos

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")

=> 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

Page 7: Ruby en 20 minutos

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 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")

Page 8: Ruby en 20 minutos

@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

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

Page 9: Ruby en 20 minutos

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}"

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?

Page 10: Ruby en 20 minutos

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.

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.

Page 11: Ruby en 20 minutos

# 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.

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.

Page 12: Ruby en 20 minutos

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.