Tutorial Ruby Peru

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 103

Nmeros

Ahora que tienes todo instalado, vamos a escribir un


programa! Abre tu editor de texto favorito y escribe lo siguiente:
puts 1+2

Guarda tu programa (s, eso es un programa!) como calc.rb (el


.rb es lo que usualmente ponemos al final de los programas
escritos en Ruby). Ahora ejecuta tu programa escribiendo ruby
calc.rb en la lnea de comandos. Deberas obtener un 3 en tu
pantalla. Lo ves?, programar no es tan difcil, cierto?

Introduccin a puts
Cmo es que funciona ese programa? Seguramente puedes
adivinar qu es lo que 1+2 hace; nuestro programa es
bsicamente lo mismo que:
puts 3

simplemente escribe en la pantalla lo que sea que


escribamos a continuacin.
puts

Enteros y flotantes
En la mayora de los lenguajes de programacin (y Ruby no es
la excepcin) los nmeros sin decimales son llamados enteros
(traduccin de integers en su versin en Ingls), y los nmeros

con punto decimal normalmente son llamados nmeros de


punto flotante (o llamados slo flotantes de ahora en adelante
ya que proviene de su original en ingls floats).
Aqu hay algunos enteros:
5
-205
9999999999999999999999999
0

Y aqu hay algunos flotantes:


54.321
0.001
-205.3884
0.0

En la prctica, la mayora de los programas no usan flotantes,


slo enteros. (Despus de todo, nadie quiere leer 7.4 emails, o
navegar 1.8 pginas, o escuchar 5.24 de sus canciones
favoritas...) Los flotantes se usan ms con propsitos
acadmicos (como por ejemplo experimentos cientficos) y para
grficos en 3D. Incluso la mayora de los programas financieros
usan enteros, simplemente llevan un registro de los centavos!

Aritmtica simple
Hasta ahora, tenemos todo lo que necesita una calculadora
simple. (Las calculadoras siempre usan flotantes, as que si
quieres que tu computadora acte como una calculadora,
tambin deberas usar flotantes). Para suma y resta, usamos +
y -, como ya lo vimos. Para la multiplicacin, usamos *, y para
la divisin usamos /. La mayora de los teclados tienen estas
teclas en el teclado numrico a la derecha. Intentemos expandir

un poco nuestro programa calc.rb. Escribe lo siguiente y


ejectalo:
puts
puts
puts
puts

1.0
2.0
5.0
9.0

+ 2.0
* 3.0
- 8.0
/ 2.0

Esto es lo que retorna el programa:


3.0
6.0
-3.0
4.5

(Los espacios en el programa no son importantes; simplemente


hacen que el cdigo sea ms fcil de leer). Bueno, eso no fue
muy sorprendente. Ahora probemos con enteros:
puts
puts
puts
puts

1+2
2*3
5-8
9/2

Bsicamente lo mismo, no?


3
6
-3
4

Uh... excepto por el ltimo! Pero cuando se hace aritmtica con


enteros, se obtienen enteros. Cuando tu computadora no
puede obtener la respuesta "correcta", siempre redondea hacia
abajo (Por supuesto, 4 es la respuesta correcta en aritmtica
con enteros para 9/2; simplemente tal vez no sea el resultado
que esperaba).
Tal vez te preguntes para qu es til la divisin entera. Bueno,
digamos que va al cine, pero slo tiene $9. Aqu en Portland,
puede ver una pelcula en el Bagdad por $2. Cuntas
pelculas puede ver all? 9/2... 4 pelculas. 4.5 definitivamente
no es la respuesta correcta ya que no le dejarn ver la mitad de

una pelcula o dejar que una mitad suya vea la pelcula entera...
algunas cosas simplemente no son divisibles.
As que ahora experimenta con algunos programas por tu
cuenta! Si quiere escribir expresiones ms complejas, puede
usar parntesis. Por ejemplo:
Cdigo:
puts 5 * (12-8) + -15
puts 98 + (59872 / (13*8)) * -52

Resultado:
5
-29802

Algunas cosas por intentar


Escribe un programa que te diga:

cuntas horas hay en un ao?


cuntos minutos hay en una dcada??
cuntos segundos de edad tiene usted?
cuntos chocolates espera comer en su vida?
Advertencia: Esta parte del programa puede tomar tiempo
para computarse!
Aqu hay una pregunta ms difcil:

Si tengo 1031 millones de segundos de edad, cuntos aos


tengo?
Cuando termine de jugar con nmeros, echemos un vistazo a
algunos textos.

Textos
As que hemos aprendido todo acerca de nmeros, pero qu
acerca de letras? palabras? textos?
Nos referimos a grupos de letras en un programa como textos.
(T puedes pensar en letras impresas siendo ensartadas en un
cartel.) Aqu hay algunos textos:
'Hola.'
'Ruby la rompe.'
'5 es mi nmero favorito... Cul es el tuyo?'
'Snoopy dice #%^?&*@! cuando le aplastan el dedo del pie.'
'
'
''

Como puedes ver, los textos pueden tener puntuacin, dgitos,


smbolos, y espacios dentro... ms que solo palabras. Ese
ltimo texto no tiene nada y podemos llamarlo un texto vaco.
Hemos estado usando puts para imprimir nmeros,
intentmoslo con textos:
Cdigo:
puts 'Hola, mundo!'
puts ''
puts 'Adis.'

Resultado:

Hola Mundo
Adis

Eso funcion bien. Ahora intntalo con algn texto tuyo.

Aritmtica de textos
Igual que hacer hacer aritmtica con nmeros, t puedes
tambin hacer aritmtica con textos! Bueno, algo as... puedes
sumar textos, digamos. Intentemos sumar dos textos y ver que
hace puts con eso.
Cdigo:
puts 'Me gusta' + 'el pastel de manzana.'

Resultado:
Me gustael pastel de manzana

Whoops! Me olvid de poner un espacio entre 'Me gusta' y 'el


pastel de manzana.'. Los espacios no importan generalmente
salvo si lo hacen dentro de los textos. (Es verdad lo que dicen:
las computadoras no hacen lo que t quieres que hagan, solo
lo que t le dices que hagan) Intentmoslo nuevamente:
Cdigo:
puts 'Me gusta ' + 'el pastel de manzana.'
puts 'Me gusta' + ' el pastel de manzana.'

Resultado:
Me gusta el pastel de manzana
Me gusta el pastel de manzana

(Como puedes ver, no import a que texto le agregu el


espacio)
As que puedes sumar textos, pero tambin puedes
multiplicarlas! (Por un nmero ...) Observa esto:
Cdigo:
puts 'parpadeo ' * 4

Resultado:

batea tus prpados

(Solo bromeaba, en realidad muestra esto):


parpadeo parpadeo parpadeo parpadeo

Si lo piensas, tiene todo el sentido. Despus de todo, 7*3


realmente solo significa 7+7+7, as que 'moo'*3 solo significa
'moo'+'moo'+'moo'.

12 vs '12'
Antes de ir ms all, debemos asegurarnos de entender la
diferencia entre nmeros y dgitos. 12 es un nmero, pero '12'
es un texto de dos dgitos.
Juguemos con esto un poco:
Cdigo:
puts 12 + 12
puts '12' + '12'
puts '12 + 12'

Resultado:
24
1212
12 + 12

Y qu sucede con esto?:


Cdigo:
puts 2 * 5
puts '2' * 5
puts '2 * 5'

Resultado:
10
22222

2 * 5

Estos ejemplos fueron bastante directos. De cualquier modo, si


no tienes cuidado en cmo mezclas tus textos y tus nmeros
podras encontrarte con...

Problemas
En este punto podras haber probado algunas cosas que no
funcionaron. Si no lo has hecho, aqu hay algunas:
Cdigo:
puts '12' + 12
puts '2' * '5'

Resultado:

can't convert Fixnum into String (TypeError)

Hmmm... un mensaje de error. El problema es que en realidad


no puedes sumar un nmero a un texto, o multiplicar un texto
por otro texto. No tiene ms sentido que esto:
puts 'Betty' + 12
puts 'Fred' * 'John'

Algo ms para tener cuidado: Puedes escribir 'pig'*5 en un


programa, dado que slo significa 5 veces el texto 'pig' todo
sumado. De cualquier modo, t no puedes escribir 5*'pig', ya
que eso significa 'pig' veces el nmero 5, lo cual es
simplemente tonto.
Finalmente, y si quisieras que tu programa imprimiera
nombre es O'hara!? Podras intentar:

Mi

puts 'Mi nombre es O'hara!'

Bueno, eso no funcionar; No intentar ni ejecutarlo. La

computadora pens que habamos terminado con el texto.


(Esta es la razn de porque es lindo tener un editor de texto
que haga coloreo sintctico por ti) Entonces, cmo permitimos
que la computadora sepa que queremos permanecer en el
texto? Tenemos que escapar el apstrofe, de esta manera:
puts 'Mi nombre es O\'hara!'

La barra invertida es el carcter de escape. En otras palabras,


si t tienes una barra invertida y otro carcter, ellos a veces son
convertidos a otro carcter. Las nicas cosas que una barra
invertida escapa son los apstrofes y las propias barras
invertidas. (Si lo piensas un poco, los caracteres escapados
siempre se escapan a s mismo) Unos pocos ejemplos
vendran muy bien, me parece:
Cdigo:
puts
puts
puts
puts

'Mi nombre es O\'hara!'


'barra invertida al final del texto: \\'
'arriba\\abajo'
'arriba\abajo'

Resultado:

Mi nombre es O'hara!
barra invertida al final del texto: \
arriba\abajo
arriba\abajo

Dado que la barra invertida no escapa un `'d', pero si si se


escapa a si misma, esos dos ltimos caracteres son idnticos.
No parecen lo mismo en el cdigo, pero en tu computadora son
realmente los mismos.
Si tienes alguna pregunta, solo sigue leyendo! No podra
contestar cada pregunta en esta pgina, despus de todo.

Variables
Hasta ahora, cuando usamos 'puts' para un texto o nmero,
esto desaparece. A lo que me refiero es que, si queremos
imprimir algo dos veces, necesitamos escribirlo dos veces:
Cdigo:
puts '...puedes decir eso de nuevo...'
puts '...puedes decir eso de nuevo...'

Resultado:

...puedes decir eso de nuevo...


...puedes decir eso de nuevo...

Sera bueno si pudiesemos escribirlo solo una vez y


quedrnoslo... guardarlo en algn lado. Bueno, s podemos, por
supuesto; de otra manera, no lo hubiese mencionado!
Para guardar el texto en la memoria de tu computador,
necesitamos darle un nombre al texto. Los programadores se
refieren frecuentemente a este proceso como asignacin y
llaman a los nombres variables. Esta variable puede ser
cualquier secuencia de letras o nmeros, pero el primer
caracter necesita ser minscula. Probemos nuestro programa
de nuevo, pero esta vez voy a darle el nombre 'myString' al texto
(aunque podra haber usado cualquier nombre, por ejemplo 'str'
or 'myOwnLittleString' or 'henryTheEighth').
Cdigo:
myString = '...puedes decir eso de nuevo...'
puts myString
puts myString

Resultado:

...puedes decir eso de nuevo...

...puedes decir eso de nuevo...

En todo momento cuando haces referencia a 'myString', el


programa usa en su reemplazo "'...puedes decir eso de nuevo...'".
Puedes pensar en la variable 'myString' como "apuntando" al
texto "'...puedes decir eso de nuevo...'". Este es un ejemplo un
poco ms interesante.
Cdigo:
name = 'Patricia Rosanna Jessica Mildred Oppenheimer'
puts 'Me llamo ' + name + '.'
puts 'Wow! "' + name + '" es un nombre realmente largo!'

Resultado:

Me llamo Patricia Rosanna Jessica Mildred Oppenheimer


Wow! Patricia Rosanna Jessica Mildred Oppenheimer es un nombre
realmente largo!

Tambin, as como podemos asignar un objeto a una variable,


podemos reasignar un objeto diferente a esa variable (Por eso
es que las llamamos variables: porque varan.)
Cdigo:
composer = 'Mozart'
puts composer + ' fue "el amo", en su da.'
composer = 'Beethoven'
puts 'Pero yo prefiero a ' + composer + ', personalmente.'

Resultado:

Mozart fue "el amo", en su da.


Pero yo prefiero a Beethoven, personalmente.

Por supuesto, las variables pueden apuntar a cualquier tipo de


objeto, no slo texto:
Cdigo:
var = 'solo otro ' + 'texto'
puts var
var = 5 * (1+2)

puts var

Resultado:
solo otro texto
15

De hecho, las variables pueden apuntar a casi cualquier cosa...


excepto otras variables. Pero qu pasa si lo intentamos?
Cdigo:
var1 = 8
var2 = var1
puts var1
puts var2
puts ''
var1 = 'ocho'
puts var1
puts var2

Resultado:
8
8
ocho
8

Primero, cuando tratamos de apuntar var2 a var1 en realidad


apuntamos a 8 (que es el valor al cual apuntaba var1). Luego
cuando apuntamos var1 a 'ocho', el valor de var2 no cambia ya
que en realidad no estaba apuntando a var1 sino a 8. Ahora
que tenemos variables, nmeros y textos, vamos a ver como
mezclarlos.

Mezclando
Hemos revisado distintos tipos de objetos (nmeros y textos) y
hemos hecho que variables apunten a ellos; lo que queremos

hacer despus es que funcionen todos juntos.


Hemos visto que si queremos que un programa imprima 25, lo
que sigue no funciona, porque no puedes sumar nmeros y
texto:
Cdigo:
var1 = 2
var2 = '5'
puts var1 + var2

Resultado:
in `+': String can't be coerced into Fixnum (TypeError)

Parte del problema es que tu computadora no sabe si estabas


tratando de obtener 7 (2 + 5) o si queras obtener '25' ('2' + '5').
Antes de poderlos sumar, necesitamos alguna forma de
conseguir la representacin textual (en 'letras') de var1, o la
representacin numrica de var2.

Conversiones
Para obtener la representacin en texto de un objeto,
simplemente escribiendo .to_s despus de el objeto:
Cdigo:
var1 = 2
var2 = '5'
puts var1.to_s + var2

Resultado:
25

De la misma manera, to_i devuelve la versin numrica entera


de un objeto y to_f devuelve la versin de punto flotante, o sea
la que lleva decimales. Veamos que hacen estos tres mtodos
(y lo que no hacen) un poco ms de cerca:
Cdigo:
var1 = 2
var2 = '5'
puts var1.to_s + var2
puts var1 + var2.to_i

Resultado:
25
7

Nota que, inclusive despus de que obtuvimos la versin en


texto de var1 al llamar to_s, var1 siempre apunt a 2, y nunca a
'2'. A menos que reasignes explcitamente var1 (lo que requiere
de un signo =), apuntar a 2 durante la duracin del programa.
Ahora probemos conversiones ms interesantes (y un poco
raras):
Cdigo:
puts
puts
puts
puts
puts
puts
puts
puts

'15'.to_f
'99.999'.to_f
'99.999'.to_i
'5 es mi numero favorito.'.to_i
'Quin pregunta acerca de 5 o lo que sea?'.to_i
'Tu mam hizo.'.to_f
'fibroso'.to_s
3.to_i

Resultado:
15.0
99.999
99
5
0
0.0

fibroso
3

sto probablemente te ha sorprendido un poco. El primero es


bastante estndar, devolviendo 15.0. Despus de eso,
convertimos el texto '99.999' a un nmero de punto flotante y a
un entero. El primero hizo lo que esperbamos; el entero fue,
como siempre, redondeado hacia abajo.
Luego, tuvimos ejemplos de algunos textos... inusuales ...
convertidos a nmeros to_i ignora lo primero que no entienda, y
el resto del texto a partir de ah. As que lo primero va a ser
convertido a 5, pero los otros, ya que comenzaban con letras,
fueron ignorados completamente... as que la computadora
simplemente elige usar cero.
Finalmente, vimos que las ltimas dos conversiones no hacan
nada, tal como esperbamos.
Hay algo extrao en nuestro mtodo favorito... Mira esto:
Cdigo:
puts 20
puts 20.to_s
puts '20'

Resultado:
20
20
20

Por qu estas tres lneas retornan el mismo resultado? Bueno,


las ltimas dos deberan, ya que 20.to_s es '20'. Pero, qu
pasa con la primera, el entero 20? Para tal caso, qu significa
escribir el entero 20? Cuando escribes 2 y luego 0 en un papel,
estas escribiendo texto, no un entero. El entero 20 es el nmero
de dedos que tengo; no es 2 seguido de un 0.

Bueno, ah est el secreto de nuestro amigo puts. Antes de que


puts trate de imprimir un objeto, usa to_s para obtener la versin
en texto de ese objeto. De hecho, la s en puts significa string
(que en espaol significa texto); puts realmente significa put
string (que en espaol significa imprimir texto).
Esto puede no parecer muy emocionante ahora, pero hay
muchos, muchos objetos en Ruby (inclusive vas a aprender a
crear tus propios objetos!), y es bueno saber que va a pasar
cuando trates de ejecutar puts con un objeto bastante raro,
como la foto de tu abuela, o un archivo de msica, etc. Pero
eso vendr despus ...
Mientras tanto, tenemos unos cuantos mtodos para ti, y ellos
nos permiten escribir todo tipo de programas divertidos ...

Los Mtodos gets y chomp


Si puts significa put string, estoy seguro que puedes adivinar
que significa gets, get string (recibir texto). Y as como puts
siempre devuelve texto, gets slo funciona con texto. Y de
dnde lo recibe?
De ti! Bueno, de tu teclado, en realidad. Ya que tu teclado slo
escribe texto, todo funciona bien. Lo que realmente pasa es
que gets simplemente lee todo lo que tipeas hasta que
presionas Enter. Intentmoslo:
Cdigo:
puts gets

Resultado:

*Hay eco aqu?*


Hay eco aqu?

Por supuesto, lo que sea que escribas simplemente ser


impreso en pantalla por ti. Ejectalo unas cuantas veces e
intenta escribir cosas distintas.
Ahora podemos escribir programas interactivos! En este caso,
escribe tu nombre y te saludar:
puts 'Hola, cul es tu nombre?'
name = gets
puts 'Tu nombre es ' + name + '? Es un nombre adorable!'
puts 'Encantado de conocerte, ' + name + '. :)'

Uhm! Acabo de ejecutarlo, escrib mi nombre y esto es lo que


he obtenido:
Hola, cul es tu nombre?
*Chris*
Tu nombre es Chris
? Es un nombre adorable!
Encantado de conocerte, Chris
. :)

Hmmm... parece que cuando escrib las letras C, h, r, i, s, y


luego presion Enter, gets recibi todas las letras de mi nombre
y el Enter! Afortunadamente, hay un mtodo para este tipo de
cosas: chomp. sto elimina cualquier Enter al final del texto.
Intentmoslo de nuevo, pero con chomp para que nos ayude:
Cdigo:
puts 'Hola, cul es tu nombre?'
name = gets.chomp
puts 'Tu nombre es ' + name + '? Es un nombre adorable!'
puts 'Encantado de conocerte, ' + name + '. :)'

Resultado:

Hola, cul es tu nombre?


Chris
Tu nombre es Chris? Es un nombre adorable!
Encantado de conocerte, Chris. :)

Mucho mejor! Nota que ya que name apunta a gets.chomp, no

tenemos que usar name.chomp; name ya fue procesado por


`chomp.

Algunas cosas por intentar

Escribe un programa que pregunte por el nombre de una


persona, luego el segundo nombre y luego el apellido.
Finalmente, debera saludar a la persona con el nombre
completo.

Escribe un programa que pregunte por el nmero favorito del


usuario. Haz que tu programa agregue un nmero, luego
sugiera el resultado como el nmero favorito pero ms grande
y mejorado (Pero hazlo con tacto).
Una vez que hayas terminado los dos programas (y otros que
hayas intentado), tratemos de aprender ms (y ms sobre)
mtodos!.

Ms acerca de
Mtodos
Hemos visto diferentes mtodos: puts, gets, etc. (Prueba: Listar
todos los mtodos que hemos visto hasta ahora!. Hay diez de
ellos, la respuesta est abajo), pero no hemos realmente
hablado sobre que hacen los mtodos. Sabemos que hacen,
pero no lo que son.

Pero realmente, esto es lo que son: cosas que generan otras.


Si objetos (como textos, enteros y flotantes) son los sujetos en
el lenguaje Ruby, entonces los mtodos son como verbos. Y,
justo como en el espaol, t no puedes tener un verbo sin un
sustantivo para hacer algo. Por ejemplo, tic-tac no es algo que
slo ocurre; un reloj (o algo) tiene que hacer esto. En espaol
podemos decir: "El reloj hace tic-tac". En Ruby podemos decir
clock.tick (asumiendo por supuesto que clock es un objeto
Ruby). Los programadores pueden decir que estamos
"llamando el mtodo tick de clock" o llamamos al "tick de clock".
Entonces, has hecho la prueba? Bien. Bueno, estoy seguro
que recordaras los mtodos puts, gets, y chomp, dado que ya
hablamos sobre ellos. Probablemente tambin recuerdas los
mtodos de conversin to_i, to_f, y to_s. Sin embargo, has visto
los otros cuatro? Porque, estos no son otros que nuestros
viejos amigos para la aritmtica +, -, *, y /!
Entonces, como cada verbo necesita un sustantivo, entonces
cada mtodo necesita un objeto. Esto es generalmente fcil de
indicar: es el que viene justo antes de un punto, como nuestro
ejemplo clock.tick, o en 101.to_s. Algunas veces, sin embargo,
esto no es tan obvio; como con los mtodos aritmticos. Como
resulta, 5 + 5 es solo otra forma fcil de escribir 5.+ 5. Por
ejemplo:
Cdigo:
puts 'hola '.+ 'mundo'
puts (10.* 9).+ 9

Resultado:
hola mundo
99

Esto no es muy lindo, por lo que no vamos a escribir siempre

como ahora; sin embargo, es importante para entender que


sucede realmente.
Esto tambin nos da un profundo entendimiento de porque
podemos hacer 'pig'*5 pero no podemos hacer 5*'pig': 'pig'*5
est diciendo a 'pig' de hacer de multiplicando, pero 5*'pig' est
diciendo a 5 de hacer de multiplicando. 'pig' sabe como hacer 5
copias de si mismo y agregar todos ellos juntos; sin embargo, 5
tendr mucha mas dificultad en tiempo de hacer 'pig' copias de
si mismo y sumarlos a todos juntos.
Y, por supuesto, continuaremos teniendo puts y gets para
explicar. Dnde estn sus objetos? En espaol, puedes
algunas veces dejar fuera el sustantivo; por ejemplo, si un
villano grita "Muere!", el sustantivo implcito es a quien l est
gritando. En Ruby, si digo puts 'ser o no ser', lo que realmente
estoy diciendo es self.puts 'ser o no ser'.
Entonces que es self? sta es una variable especial que
apunta al objeto en el que ests. No siempre sabemos como
estar en un objeto, pero hasta que nos demos cuenta, siempre
iremos a estar en un gran objeto que es... el programa entero!
(sin embargo en este caso no es posible llamarlo en forma
explcita) Observa lo siguiente:
Cdigo:
NoPuedoCreerQueUnaVariableConNombreTanLargoApunteA3 = 3
puts NoPuedoCreerQueUnaVariableConNombreTanLargoApunteA3
self.puts NoPuedoCreerQueUnaVariableConNombreTanLargoApunteA3

Resultado:

3
in `<main>': private method `puts' called for main:Object
(NoMethodError)

Si no alcanzaste a comprender todo, est bien. Lo importante

es que todo mtodo est siendo propiedad de un objeto,


incluso si no tiene un punto enfrente de este. Si entiendes esto
ests preparado.

Mtodos imaginativos acerca


de Strings
Vamos a aprender unos pocos pero interesantes mtodos. No
tienes porque memorizar todos; puedes mirar esta pagina de
nuevo si te olvidas de alguno. Yo slo quiero mostrarte una
pequea parte de lo que puede hacer un texto. De hecho, no
recuerdo ni siquiera la mitad de los mtodos para textos; pero
est bien, porque hay buenas referencias en internet con todo
acerca de textos listados y explicados (Voy a mostrarte donde
encontrar esas referencias al final del tutorial).
Realmente, tampoco quiero saber todo acerca de los mtodos
para textos; sino sera como tratar de conocer cada palabra en
el diccionario. Puedo hablar espaol bien sin conocer cada una
de las palabras del diccionario... y no es ese realmente el
objetivo del diccionario? Entonces no tienes que conocer que
hay en ste?
Entonces, nuestro primer mtodo para texto es reverse, el cual
nos da una version invertida de un texto:
Cdigo:
var1 = 'parar'
var2 = 'subrayado'
var3 = 'Puedes pronunciar esta oracin al reves?'

puts
puts
puts
puts
puts
puts

var1.reverse
var2.reverse
var3.reverse
var1
var2
var3

Resultado:
rarap
odayarbus
?sever la nicaro atse raicnunorp sedeuP
parar
subrayado
Puedes pronunciar esta oracin al reves?

Como puedes ver, reverse no revierte el orden en el string


original; ste slo hace una nueva versin de ste en reversa.
Esto es porque var1 continua 'parar' an despus de que
llamamos reverse sobre var1.
Otro mtodo para texto es length, el cual nos dice el nmero de
caracteres (incluyendo caracteres) en el texto:
Cdigo:
puts 'Cul es tu nombre completo?'
name = gets.chomp
puts 'Sabes que hay ' + name.length + ' caracteres en tu nombre, '
+ name + '?'

Resultado:
Cul es tu nombre completo?
Christopher David Pine
#<TypeError: can't convert Fixnum into String>

Uhh!! Algo sali mal, y esto parece que ocurri despus la


lnea name = gets.chomp... Puedes ver el problema? Fijate si
puedes darte cuenta.
El problema es con length: esto te devuelve un nmero, pero
nosotros queremos un texto. Esto es fcil, necesitamos solo
agregar to_s (y cruzar nuestros dedos):

Cdigo:
puts 'Cul es tu nombre completo?'
name = gets.chomp
puts 'Sabas que hay ' + name.length.to_s + ' caracteres en tu
nombre, ' + name + '?'

Resultado:

Cul es tu nombre completo?


Christopher David Pine
Sabas que hay 22 caracteres en tu nombre, Christopher David Pine

No, no conoca esto. Nota: esto es el nmero de caracteres en


mi nombre, no el nmero de letras. Supongo que podramos
escribir un programa el cual nos pregunte por nuestro primer
nombre, segundo nombre y apellidos individualmente, y
entonces sumar estos tamaos todos juntos... hey, porque no
haces sto! Comienza, esperar.
Lo hiciste? Bien! Es un lindo programa, no? Despus de
unos pocos captulos ms, pienso, estars sorprendido de lo
que podrs hacer.
Entonces, hay tambin un nmero de mtodos para texto los
cuales cambian el contenido (maysculas y minsculas) de tu
texto. upcase cambian cada minscula por mayscula. swapcase
cambia en cada letra en el string("Hola".swapcase #=>
"hOLA"), y finalmente, capitalize es como downcase, excepto que
esto cambia solo el primer carcter a maysculas(si es una
letra).
Cdigo:
letters = 'aAbBcCdDeE'
puts letters.upcase
puts letters.downcase
puts letters.swapcase
puts letters.capitalize
puts ' a'.capitalize
puts letters

Resultado:
AABBCCDDEE
aabbccddee
AaBbCcDdEe
Aabbccddee
a
aAbBcCdDeE

Esto es bastante estndar. Como puedes ver desde la linea


puts ' a'.capitalize, el mtodo capitalize slo deja en maysculas
el primer carcter, no la primera letra. Tambin, como hemos
visto antes, en todas estas llamadas a mtodos, letters
permanece igual. No quiero decir que se dedica slo a sto,
pero es importante entenderlo. Hay algunos mtodos los cuales
hacen cambios a los objetos asociados, pero no los hemos
visto an, y no lo haremos por algn tiempo.
El ltimo tipo de mtodos que veremos son los de formato
visual. El primero es, center, suma espacios al comienzo y final
para hacer que este centrado. Sin embargo, slo tienes que
decir puts a lo que quieres imprimir, y + a lo que quieres sumar,
pero tienes que decir a center que ancho tiene que tener el
string centrado. Entonces si quiero centrar las lineas de un
poema, debera hacer algo como esto:
Cdigo:
lineWidth = 50
puts(
'Old Mother Hubbard'.center(lineWidth))
puts(
'Sat in her cupboard'.center(lineWidth))
puts(
'Eating her curds an whey,'.center(lineWidth))
puts(
'When along came a spider'.center(lineWidth))
puts(
'Which sat down beside her'.center(lineWidth))
puts('And scared her poor shoe dog away.'.center(lineWidth))

Resultado:
Old Mother Hubbard
Sat in her cupboard
Eating her curds an whey,
When along came a spider

Which sat down beside her


And scared her poor shoe dog away.

Mmmm.. no pienso que esto es un campamento de verano,


pero estoy muy cansado para buscar esto. (Entonces, quise
alinear la parte .center lineWidth , entonces puse esos espacios
extras antes de los textos. Esto es as slo porque pienso que
es ms lindo de esta forma. Los programadores generalmente
tienen duros conceptos acerca de que es lindo en un programa,
y a menudo confrontan acerca de esto. Cuanto ms programes,
ms lograras tu propio estilo.) Hablando de ser perezoso a la
hora de programar, lo cual no es siempre algo malo en
programacin. Por ejemplo, fjate como guard el ancho del
poema en la variable lineWidth? Esto es que si entonces quiero
regresar ms tarde y hacer el poema ms ancho, solo tengo
que cambiar la variable al comienzo del programa, antes que
en cada lnea. Con un poema muy largo, esto podra ahorrarme
un montn de tiempo. Este tipo de pereza es realmente una
virtud en programacin.
Entonces, acerca del centrado... t te dars cuenta que esto no
es muy lindo como podra serlo un procesador de texto. Si
realmente quieres un perfecto centrado (y quizs una fuente
mas linda), entonces deberas slo usar un procesador de
textos!. Ruby es una herramienta maravillosa, pero no la
herramienta correcta para cualquier trabajo.
Los otros dos mtodos de formato de textos son ljust y rjust, lo
cual significan justificado izquierdo y justificado derecho. Estos
son similares a center, excepto que ellos rellenan los lados
derecho e izquierdo respectivamente. Vamos a verlos en
accin:
Cdigo:

lineWidth = 40
str = '--> text <--'
puts str.ljust lineWidth
puts str.center lineWidth
puts str.rjust lineWidth
puts str.ljust(lineWidth/2) + str.rjust(lineWidth/2)

Resultado:
--> text <---> text <---> text <---> text <---> text <--

Algunas cosas por intentar

Escribe un programa Jefe Enojado. Este debe preguntar de mala


manera qu quieres. Cualquier cosa que consultes, el Jefe
Enojado deber devolverte la consulta de mala forma, y luego
despedirte. Por ejemplo, si tu escribes Quiero un aumento.,
deber contestarte PERO QUE DICES HOMBRE "QUIERES UN
AUMENTO."?!? ESTAS DESPEDIDO!!

Entonces aqu hay algo para que puedas jugar un poco ms


con center, ljust, y rjust: Escribe un programa el cual muestre
una Tabla de Contenidos que se parezca a lo siguiente:
Listado:
Tabla de Contenidos
Captulo 1: Nmeros
Captulo 2: Letras
Captulo 3: Variables

pgina 1
pgina 72
pgina 118

Matemticas Avanzadas

(Esta seccin es totalmente opcional. Asume un conocimiento


previo de matemticas. Si no ests interesado, puedes ir
directamente al siguiente captulo Control de Flujo sin
problemas. Aunque, una rpida vista de esta seccin sobre
*Nmeros aleatorios** debera venir bien.)*
No hay tantos mtodos numricos como los hay para textos
(pienso que aun no los conozco a todos sin recurrir a la ayuda
de documentacin). Aqu, vamos a mirar el resto de los
mtodos aritmticos, un generador de nmeros aleatorios, y el
objeto Math , con sus mtodos trigonomtricos y
transcendentales.

Ms de aritmtica
Los otros dos mtodos aritmticos son ** (potencia) y %
(mdulo). Entonces si quieres decir "cinco al cuadrado" en
Ruby, deberas escribir algo as 5**2. Tambin puedes usar
flotantes para tus exponentes, entonces si quieres una raz
cuadrada de 5, deberas escribir 5**0.5. Los mtodos mdulo te
dan el sobrante despus de una divisin por un nmero.
Entonces, por ejemplo, si divido 7 por 3, obtengo 2 con un
remanente de 1. Vamos a ver como es que trabaja en un
programa:
Cdigo:
puts
puts
puts
puts
puts

5**2
5**0.5
7/3
7%3
365%7

Resultado:
25
2.23606797749979
2
1
1

De la ltima lnea, aprendimos que un ao (no bisiesto) tienen


algn nmero de semanas, ms un da. Entonces si tu
cumpleaos fue un Martes este ao, el prximo ao ser un
Mircoles. Tu tambin puedes usar flotantes con el mtodo
mdulo (%). Bsicamente, funciona de una manera lgica...
pero voy a mostrar un poco mas como trabajar con esto.
Hay un ltimo mtodo para mencionar antes de revisar el
mtodo random: abs. ste slo toma el valor absoluto de un
nmero:
Cdigo:
puts((5-2).abs)
puts((2-5).abs)

Resultado:
3
3

Nmeros aleatorios
Ruby viene con un lindo generador de nmeros aleatorios. El
mtodo para obtener un nmero aleatorio es rand. Si llamas
rand , obtendrs un nmero flotante mayor o igual a 0.0 y menor
a 1.0. Si le proporcionas a rand un nmero entero (5 por
ejemplo), esto te devolver un entero mayor o igual a 0 y menor
a 5 (entonces son cinco nmeros posibles, de 0 a 4).

Vamos a ver rand en accin.


Cdigo:
puts rand
puts rand
puts rand
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(1))
puts(rand(1))
puts(rand(1))
puts(rand(99999999999999999999999999999999999999999999999
999999999999))
puts('El pronosticador del tiempo dijo que hay '+rand(101).to_s+'%
chances de que llueva,')
puts('pero nunca debes confiar en el.')

Resultado:

0.866769322351658
0.155609260113273
0.208355946789083
61
46
92
0
0
0
2298247750813186023195410877388752386160069398951849569
9862
El pronosticador del tiempo dijo que hay 47% chances de que llueva,
pero nunca debes confiar en el.

Fijate que utilic rand(101) para obtener nmeros entre 0 y 100,


y que el rand(1) siempre devuelve 0. No entender el rango
posible de retorno de valores es el error ms grande que veo
en gente que hace rand; an programadores profesionales, ms
an en productos finalizados que puedes comprar. Incluso tena
un reproductor de CD que si se configuraba en "Reproduccin
aleatoria," reproducia todas las canciones menos la ltima ...
(Me pregunto qu hubiera pasado si hubiera puesto un CD
con slo una cancin en ella?)

Algunas veces querrs que rand retorne el mismo random de


nmeros incluso en la misma secuencia en dos diferentes
ejecuciones de tu programa. (Por ejemplo, una vez estaba
utilizando nmeros generados aleatoriamente para crear un
mundo al azar por un juego de computadoras. Encontr un
mundo que realmente me gust, quizs me hubiera gustado
jugar de nuevo con ste o enviarlo a un amigo.) Con el fin de
hacer esto, tu necesitas configurar la "generacin de ste", lo
que se puede hacer con srand. Como lo siguiente:
Cdigo:
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts ''
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))

Resultado:
24
35
36
58
70
24
35
36
58
70

Esto har la misma cosa cada vez que inicies con el mismo
nmero. Si quieres obtener diferentes nmeros(como pasara si
nunca utilizaras srand), entonces slo llamas a srand 0. Esto

inicializa con un nmero realmente raro, utilizando (adems de


otras cosas) la hora actual de tu computadora, hasta los
milisegundos.

El Objeto Math
Finalmente, vamos a echar un vistazo al objeto Math.
Deberamos ir directamente a este:
Cdigo:
puts(Math::PI)
puts(Math::E)
puts(Math.cos(Math::PI/3))
puts(Math.tan(Math::PI/4))
puts(Math.log(Math::E**2))
puts((1 + Math.sqrt(5))/2)

Resultado:

3.14159265358979
2.71828182845905
0.5
1.0
2.0
1.61803398874989

La primera cosa de la que te habrs dado cuenta es


probablemente de la notacin ::. Explicando el alcance del
operador (que es esto) esta fuera del objetivo de este tutorial.
Como puedes ver, Math tiene todas las cosas que podras
esperar de una calculadora cientfica decente. Y como siempre,
los flotantes estn realmente cerca de ser la respuesta
correcta.
Entonces ahora vamos a ver control de flujo.

Control de Flujo
Ahhhh, control de flujo. Ac es donde todo empieza a encajar.
A pesar que este captulo es ms corto y facil que el captulo de
mtodos, te abrir un mundo nuevo de posibilidades para
programar.
Luego de este captulo, seremos capaces de escribir
programas realmente interactivos; previamente hemos creado
programas que dicen distintas cosas dependiente de lo que
ingreses en tu teclado, pero luego de este captulo estos
tambin harn distintas cosas. Pero antes que podamos hacer
eso, necesitamos ser capaces de comparar objectos en
nuestros programas. Necesitamos...

Mtodos de comparacin
Avancemos rpidamente por esta seccin para que podamos ir
a la siguiente, Ramificaciones, donde todas las cosas geniales
ocurren. Entonces, para ver si un objeto es mayor o menor que
otro, usaremos los mtodos > y <, as:
Cdigo:
puts 1 > 2
puts 1 < 2

Resultado:
false
true

Sin problemas. De igual manera, podemos identificar si un


objeto es mayor-o-igual-que otro o menor-o-igual-que con los
mtodos >= y <=
Cdigo:
puts 5 >= 5
puts 5 <= 4

Resultado:
true
false

Finalmente, podemos ver si dos objetos son iguales o no


utilizando == (que significa "son stos iguales?") y != (que
significa "son stos diferentes?").
Es importante no confundir = con ==. = se utiliza para decirle a
una variable a que objeto apuntar (asignacin) y == se utiliza
para responder la pregunta: "Son estos dos objetos iguales?".
Cdigo:
puts 1 == 1
puts 2 != 1

Resultado:
true
true

Por supuesto, podemos comparar textos tambin. Cuando los


textos se comparan, comparan su ordenamiento lexicogrfico,
que bsicamente significa su orden en un diccionario. gato
aparece antes que perro en el diccionario, as que:
Cdigo:
puts 'gato' < 'perro'

Resultado:
true

Sin embargo, hay algo que tener en cuenta: la manera en que


las computadoras normalmente asumen que las letras
maysculas vienen antes que las letras minsculas (As es
como almacenan los caracteres en las fuentes, por ejemplo: los
caracteres en mayscula primero y en minscula despus).
Esto significa que pensar que 'Zoolgico' aparece antes que
'ave', as que si quieres encontrar que palabra aparecera antes
en un diccionario real, asegrate de utilizar downcase (o upcase
o capitalize) en ambas palabras antes de tratar de compararlas.
Un ltimo comentario antes de revisar Ramificaciones: Los
mtodos de comparacin no nos estn dando los textos 'true' o
'false' ("verdadero" y "falso" en espaol); nos estn dando los
objetos especiales true y false. (Por supuesto, true.to_s nos
devuelve 'true', que es por lo que puts imprimi 'true'.)
true

y false se utilizan todo el tiempo en...

Ramificaciones
Las Ramificaciones son un concepto simple, pero poderoso. De
hecho, es tan simple que no necesito explicarlo, solo te lo
mostrar:
Cdigo:
puts 'Hola, cual es tu nombre?'
name = gets.chomp
puts 'Hola, ' + name + '.'
if name == 'Chris'
puts 'Que nombre tan hermoso!'
end

si respondemos 'Chris':
Hola, cual es tu nombre?
Chris
Hola, Chris.
Que nombre tan hermoso!

pero si ponemos otro nombre:


Hola, cual es tu nombre?
Chewbacca
Hola, Chewbacca.

Y eso es una ramificacin. Si lo que viene luego del if es true


(es decir, si es cierto), se ejecutar el cdigo entre el if y el end.
Y no se ejecutar si lo que viene luego del if es false (falso).
Ms facil imposible.
He indentado el cdigo entre if y el end solo porque me parece
que es ms facil leer las ramificaciones de esa manera. Casi
todos los programadores lo hacen as, sin importar el lenguaje
en que estn programando. No parece ser de mucha ayuda en
este ejemplo, pero cuando las cosas se vuelven complejas, es
una gran diferencia.
Varias veces nos gustara que un programa haga alguna cosa
si una expresin es true, y otra cosa si es que es false. Para eso
es que existe else:
Cdigo:
puts 'Soy un adivino. Dime tu nombre:'
name = gets.chomp
if name == 'Chris'
puts 'Veo grandes cosas en tu futuro.'
else
puts 'Tu futuro es... Oh! Mira la hora!'
puts 'Realmente debo irme, lo siento!'
end

si respondemos 'Chris':

Soy un adivino. Dime tu nombre:

Chris
Veo grandes cosas en tu futuro.

Si tratamos con un nombre diferente:


Soy un adivino. Dime tu nombre:
Ringo
Tu futuro es... Oh! Mira la hora!
Realmente debo irme, lo siento!

Las ramificaciones son como encontrar una bifurcacin en el


cdigo: Seguimos el camino de las personas cuyo name ==
'Chris' o el camino de aquellas que no (else)?
Y como las ramas de un rbol, puedes tener ramificaciones que
a su vez tengan otras ramificaciones:
Cdigo:
puts 'Hola, y bienvenido a la clase de 7mo ao.'
puts 'Me llamo Mrs. Gabbard. T nombre es...?'
nombre = gets.chomp
if nombre == nombre.capitalize
puts 'Por favor, toma asiento ' + nombre + '.'
else
puts '' + nombre + '? Quieres decir ' + nombre.capitalize + ',
cierto?'
puts 'No sabes escribir tu propio nombre?'
respuesta = gets.chomp
if respuesta.downcase == 'si'
puts 'Hum! Bueno, sintese!'
else
puts 'SALGA DEL SALON!'
end
end

si respondemos el nombre en minsculas:


Hola, y bienvenido a la clase de 7mo ao.
Me llamo Mrs. Gabbard. T nombre es...?
chris
chris? Quieres decir Chris, cierto?
No sabes escribir tu propio nombre?
si
Hum! Bueno, sintese!

y si respondemos el nombre como debe ser:


Hola, y bienvenido a la clase de 7mo ao.
Me llamo Mrs. Gabbard. T nombre es...?
Chris
Por favor, toma asiento Chris.

Algunas veces puede ser algo confuso entender donde todos


los ifs, elses, y ends van. Lo que yo hago es escribir el end al
mismo tiempo que escribo el if. As es que como se vea al
principio el programa de arriba segn lo iba escribiendo:
puts 'Hola, y bienvenido a la clase de 7mo ao.'
puts 'Me llamo Mrs. Gabbard. T nombre es...?'
nombre = gets.chomp
if nombre == nombre.capitalize
else
end

Entonces lo llen con comentarios, cosas en el cdigo que la


computadora ignorar:
puts 'Hola, y bienvenido a la clase de 7mo ao.'
puts 'Me llamo Mrs. Gabbard. T nombre es...?'
nombre = gets.chomp
if nombre == nombre.capitalize
# Me trata como una persona normal.
else
# Se vuelve loca.
end

Todo lo que aparezca luego de un # se considera un


comentario (a menos, claro, que ests en un texto). Despus
de eso, reemplac los comentarios con cdigo funcional.
Algunas personas prefieren dejar los comentarios;
personalmente, pienso que un cdigo bien escrito normalmente
habla por si mismo. Sola utilizar ms comentarios, pero
mientras ms "flido" me volva con Ruby menos los utiliza.
Actualmente los encuentro algo distrayentes la mayor parte del
tiempo. Es una opcin personal; t encontrars tu propio estilo
(siempre en evolucin). As que mi siguiente paso se vea as:

puts 'Hola, y bienvenido a la clase de 7mo ao.'


puts 'Me llamo Mrs. Gabbard. T nombre es...?'
nombre = gets.chomp
if nombre == nombre.capitalize
puts 'Por favor, toma asiento ' + nombre + '.'
else
puts '' + nombre + '? Quieres decir ' + nombre.capitalize + ',
cierto?'
puts 'No sabes escribir tu propio nombre?'
respuesta = gets.chomp
if respuesta.downcase == 'si'
else
end
end

De nuevo, escrib los if, else, y end juntos. Realmente me ayuda


para saber "donde estoy" en el cdigo. Tambien permite que el
trabajo parezca ms sencillo ya que me permite enfocarme en
una pequea parte, como en llenar el cdigo entre if y el else. El
otro beneficio de realizarlo de esta manera es que el
computador puede entender el programa en cualquier etapa.
Cualquiera de las versiones incompletas del programa que te
mostr se podran ejecutar. No estaban finalizadas, pero eran
programas funcionales. De esa manera, podra probarlo
mientras lo escribo, lo que ayuda a ver como voy avanzando y
donde an necesito trabajar. Cuando pase todas las pruebas s
que he terminado.
Estos tipos te ayudarn a escribir programas con ramificaciones
pero tambin te ayudarn con otros tipos de control de flujo:

Bucles
A veces querrs que tu computadora haga la misma accin una
y otra vez despus de todo se supone que en eso son

buenas las computadoras.


Cuando le dices a la computadora que siga repitiendo algo,
tambin debes decirle cuando parar. Las computadoras nunca
se aburren asi que si no le indicas cuando hacerlo nunca lo
harn. Nos aseguramos que esto no pase al indicarle a la
computadora que repita ciertas partes de un programa mientras
(while) una cierta condicin sea cierta. sto funciona de manera
muy similar a como lo hace if:
Cdigo:
comando = ''
while comando != 'adios'
puts comando
comando = gets.chomp
end
puts 'Vuelve pronto!'

Respuesta:

Hola?
Hola?
Hola!
Hola!
Un gusto conocerlo
Un gusto conocerlo
Oh... que amable!
Oh... que amable!
adios
Vuelve pronto!

Y eso es un bucle. (Tal vez te has dado cuenta de la lnea vaca


que sale al inicio del resultado; viene de ejecutar el primer puts,
antes del primer gets. Cmo cambiaras el programa para
eliminar esa primera lnea? Prubalo! Funcion
+exactamente+ igual que el programa de arriba, sin contar la
primera lnea blanca?)
Los bucles nos permiten hacer una serie de cosas interesantes,

como estoy seguro te podrs imaginar. Sin embargo, tambin


pueden causar problemas si cometes un error. Qu pasara si
tu computadora se queda atrapado en un bucle infinito? Si
piensas que eso te ha ocurrido, solo presiona la tecla +Ctrl+ y
luego la +C+.
Antes de empezar a jugar con los bucles, aprendamos un par
de cosas que nos permitirn hacer nuestro trabajo ms facil.

Un poco de lgica
Echmosle un vistazo a nuestro primer programa de
condicionales una vez ms. Qu pasara si mi esposa llega a
casa, ve el programa, lo prueba y ste no le dice que ella tiene
un nombre hermoso. Yo no querra herir sus sentimientos (o
dormir en el silln) as que reescribmoslo:
Cdigo:
puts 'Hola, cual es tu nombre?'
nombre = gets.chomp
puts 'Hola, ' + nombre + '.'
if nombre == 'Chris'
puts 'Que nombre tan hermoso!'
else
if nombre == 'Katy'
puts 'Que nombre tan hermoso!'
end
end

Respuesta:

Hola, cual es tu nombre?


Katy
Hola, Katy.
Que nombre tan hermoso!

Bueno, funciona... pero no es un programa muy bonito. Por

qu no? Bueno, la mejor regla que he aprendido de


programacin es la regla DRY: Don't Repeat Yourself_ ("No te
repitas" en espaol). Probablemente podra escribir un libro
pequeo sobre por qu es tan buena esta regla. En nuestro
caso, hemos repetido la lnea puts 'Que nombre tan hermoso!'.
Por qu es tan problemtico esto? Bueno, que pasara si
cometiera un error al escribir los textos cuando reescrib el
programa? Que tal si hubiera querido cambiar de 'hermoso' a
'bonito' en ambas lneas?
Soy flojo, recuerdas? Bsicamente si quisiera que el programa
haga lo mismo cuando reciba 'Chris' o 'Katy', entonces
realmente debera hacer exactamente la misma cosa:
Cdigo:
puts 'Hola, cual es tu nombre?'
nombre = gets.chomp
puts 'Hola, ' + nombre + '.'
if (nombre == 'Chris' or nombre == 'Katy')
puts 'Que nombre tan hermoso!'
end

Respuesta:

Hola, cual es tu nombre?


Katy
Hola, Katy.
Que nombre tan hermoso!

Mucho mejor. Para hacer que funcione, he utilizado el operador


or. Los otros operadores lgicos son and y not. Siempre es una
buena idea usar los parntesis cuando trabajamos con stos.
Veamos como funcionan:
Cdigo:
soyChris
= true
soyMorado
= false
meGustaLaComida = true
comoRocas
= false

puts
puts
puts
puts
puts
puts
puts
puts
puts
puts
puts
puts

(soyChris and meGustaLaComida)


(meGustaLaComida and comoRocas)
(soyMorado and meGustaLaComida)
(soyMorado and comoRocas)
(soyChris or meGustaLaComida)
(meGustaLaComida or comoRocas)
(soyMorado or meGustaLaComida)
(soyMorado or comoRocas)
(not soyMorado)
(not soyChris)

Respuesta:
true
false
false
false
true
true
true
false
true
false

La nica de esas sentencias que te podra confundir es el or.


En espaol normalmente decimos "uno u otro, pero no los dos".
Por ejemplo, tu mam podra decir "Para postre puedes pedir
pie o torta". Ella no quiso decir que podras tener ambos!
Una computadora, por otro lado, usa or (o) para decir "uno u
otro o los dos" (Otra manera de decirlo es "al menos una de
estas debe ser cierta"). Es por eso que las computadoras son
ms divertidas que mam.

Algunas cosas por intentar

"99 botellas de cerveza en la pared..." Escribe un programa


que imprima la letra del clsico en viajes 99 botellas de cerveza
en la pared"
Escribe un programa de la Abuela Sorda. Lo que sea que le
digas a la abuela (lo que sea que escribas), ella deber
responder con HUH?! HABLA MAS FUERTE, HIJO!, a menos
que le grites (escribas todo en maysculas) Si le gritas, ella te
escuchar (o al menos creer eso) y te gritar de vuelta NO, NO
DESDE 1938!.

Para hacer el programa realmente creble, haz


que la abuela grite un ao distinto cada vez; tal vez un ao
aleatorio entre 1930 y 1950. (Esta parte es opcional y sera
mucho ms facil si lees la seccin sobre generadores de
nmeros aleatorios de Ruby al final del captulo mtodos) No
podrs dejar de hablar con la abuela hasta que le grites ADIOS.
Pista: No te olvides que chomp! 'ADIOS'con un Enter no es lo
mismo que 'ADIOS' sin uno!. Pista 2: Trata de pensar que partes
del programa deberan suceder una y otra vez. Todas ellas
deberan estar en tu bucle while.
Extiende el programa de la Abuela Sorda. Qu pasara si la
abuela no quiere que te vayas? Cuando le grites ADIOS, ella
podra pretender que no te escucha. Cambia el programa
previo para que tengas que gritar ADIOS tres veces seguidas.
Asegrate que tu programa: si gritas ADIOS` tres veces, pero
no seguidas, deberas seguir hablando con la abuela.
Aos bisiestos. Escribe un programa que pregunte por un ao
de inicio y uno de fin, y luego imprima (puts) todos los aos
bisiestos que han ocurrido entre ellos (incluyndolos si tambin
han sido estos aos bisiestos). Los aos bisiestos son
divisibles entre cuatro (como 1984 y 2004). Sin embargo, los
aos divisibles entre 100 no son aos bisiestos (como 1800 y
1900) a menos que sean divisibles por 400 (como 1600 y

2000, los cuales fueron, de hecho, bisiestos). (S, todo es


bastante confuso, pero no tanto como tener Enero en medio del
invierno, lo cual es algo que a veces sucede)
Cuando termines con ellos, tmate un descanso! Haz
aprendido un montn hasta ahora. Felicitaciones! Ests
sorprendido de la cantidad de cosas que le puedes pedir hacer
a una computadora? Unos captulos ms y sers capaz de
programar cualquier cosas. En serio! Solo mira la cantidad de
cosas que puedes hacer ahora que antes cuando no tenas
bucles y ramificaciones.
Ahora, aprendamos sobre un nuevo tipo de objeto, que permite
tener control de listas de otros objetos: matrices.

Matrices e Iteraciones
Vamos a escribir un programa el cual nos pida digitar tantas
palabras como nosotros querramos (una palabra por lnea),
continuando hasta que oprimamos Enter en una lnea vacia), el
cual luego nos devolver las palabras en orden alfabetico. OK?
Entonces... nosotros primero vamos; uh... um... hmmm...
Bueno, nosotros podramos; er... um...
T sabes, no pienso que podamos hacer esto. Necesitamos
una forma de almacenar una cantidad desconocida de palabras
y como obtener todas ellas juntas, entonces no se confundan
con otras variables. Necesitamos colocarlas en un tipo de lista.
Lo que necesitamos son matrices.
Una matriz es solo una lista en su computadora. Cada posicin

en la lista acta como una variable: puedes ver que objeto en


particular apunta a cada posicin, y puedes hacer que este
apunte a un objeto diferente. Vamos a echar un vistazo a
algunas matrices:
[]
[5]
['Hola', 'Adis']
flavor = 'vainilla'
# Esto no es una matriz, por supuesto...
[89.9, sabor, [true, false]] # ...pero esto s lo es.

Entonces primero tenemos una matriz vaca, luego una matriz


conteniendo un nmero simple, luego una matriz que contiene
dos textos. Siguiendo, tenemos una simple asignacin, luego
un array conteniendo tres objetos, de los cuales el ltimo es la
matriz '[true, false]'. Recuerda, variables no son objetos,
entonces nuestra ultima matriz es en realidad un flotante, un
texto, y una matriz. An asi si nosotros hubieramos puesto
'sabor' a punto o algo ms, esto no hubiera cambiado la matriz.
Para ayudarnos a encontrar un objeto particular en una matriz,
cada posicin es dada por un ndice numrico. Programadores
(y, por cierto, la mayora de los matemticos) comienzan
contando desde cero, por lo que la primera posicion del array
es cero. Aqu es como nosotros deberamos referenciar los
objetos en una matriz:
Cdigo:
names = ['Ada', 'Belle', 'Chris']
puts
puts
puts
puts
puts

names
names[0]
names[1]
names[2]
names[3] # Este esta fuera del rango.

Resultado:

Ada
Belle
Chris
Ada
Belle
Chris

Entonces, nosotros vemos que 'puts names' imprime cada


nombre en la matriz 'names'. Luego usamos 'puts names[0]' para
imprimir el "primer" nombre en la matriz, y 'puts names[1]' para
imprimir el "segundo" ... Estoy seguro que esto parece confuso,
pero puedes acostumbrarte a esto. Tienes que realmente solo
comenzar pensando que el contador comienza en cero, y dejas
de usar palabras como "primero" y "segundo"
Si tienes un conjunto de cinco cursos, no hablas acerca del
"primer" curso, hablas acerca del curso cero (y en tu cabeza,
ests pensando 'course[0]'). T tienes cinco dedos en tu mano
derecha, y sus nmeros son 0, 1, 2, 3 y 4. Mi esposa y yo
somos malabaristas. Cuando hacemos malabares con seis
objetos, nosotros estamos con los objetos 0-5. Esperamos en
los prximos meses, poder manejarnos con el objeto 6 (y por lo
tanto trataremos de manejarnos con 7 objetos) Tu sabrs que lo
has aprendido cuando comiences a usar la palabra "cero". S,
esto es real; pregunta a cualquier programador o matemtico.
Finalmente, tratamos 'puts names[3]', solo para ver que podra
suceder. Estabas esperando un error? Algunas veces cuando
preguntas algo, tu pregunta no tiene sentido (al menos para tu
computadora); ah es cuando obtienes un error. Algunas veces,
en cambio, tu puedes preguntar algo y la respuesta es nada.
Qu hay en la posicin tres? Nada. Qu hay en 'names[3]'?
'nil': Es la forma Ruby de decir "nada". 'nil' es un objeto especial
que significa "no hay ningn objeto".
Si todo este divertido numerado de posiciones esta

molestndote, no te preocupes! Tambin, podemos evitar esto


completamente usando varios metodos para matrices, como el
que sigue:

El Metodo 'each'
nos permite hacer algo (lo que queramos) a cada objeto
que apunte. Asi, si queremos decir algo bueno acerca de cada
lenguaje en la matriz de abajo, podriamos hacer esto:
'each'

Cdigo:
lenguajes = ['Ingls', 'Alemn', 'Ruby']
lenguajes.each do |leng|
puts 'Me gusta ' + leng + '!'
puts 'A ti?'
end
puts 'Y vamos a escuchar esto para C++!'
puts '...'

Resultado:

Me gusta Ingls!
A t?
Me gusta Alemn!
A t?
Me gusta Ruby!
A t?
Y vamos a escuchar esto para C++!
...

Qu acaba de ocurrir? Bueno, tenemos permitido ir a travs


de cada objeto en la matriz sin utilizar ningun nmero, as esto
es definitivamente mejor. Traducido al espaol diriamos que:
Para cada 'each' objeto en 'lenguajes', apunta la variable 'leng' al
objeto y entonces 'do' (do = hacer) todo lo que te digo, hasta
que llegues al 'end'. (Slo para que sepas, C++ es otro lenguaje

de programacin. Este es mucho mas difcil de aprender que


Ruby; por lo general, un programa hecho en C++ ser muchas
veces ms extenso que un programa en Ruby que haga la
misma funcionalidad)
T estars pensando para ti mismo, "Esto es un montn de
bucles como los que hemos aprendido antes". S, esto es
similar. Una diferencia importante es que el mtodo 'each' es
solo eso: un mtodo. 'while' y 'end'; tal como 'do', 'if', 'else', y
todas las otras "palabras" no lo son. Ellos son una parte
fundamental del lenguaje Ruby, tal como '=' y los parntesis
son tipos de puntuacin como en espaol.
Pero no 'each'; 'each' es solo otro mtodo de la matriz. Mtodos
como `'each' los cuales 'actuan como' bucles son a menudo
llamados iteradores.
Algo para saber sobre iteradores es que estos son siempre
seguidos por 'do'...'end'. 'while' y 'if' nunca tuvieron un 'do' cerca
de ellos; nosotros solo usamos 'do' con iteradores
Aqu hay otro pequeo iterador, pero esto no es un mtodo para
matriz... es un mtodo para entero!
Cdigo:
3.times do
puts 'Hip-Hip-Hooray!'
end

Resultado:

Hip-Hip-Hooray!
Hip-Hip-Hooray!
Hip-Hip-Hooray!

Mas mtodos para Matrices


Entonces hemos aprendido sobre 'each', pero hay muchos
mtodos ms... al menos muchos como mtodos para
matrices. De hecho, algunos de ellos (como 'length', 'reverse',
'+', y '*' ) trabajan igual que lo hacen para textos, excepto que
ellos operan sobre las posiciones de una matriz y no sobre
letras de un texto. Otros, como 'last' y 'join', son especficos de
matrices. An otros, como 'push' y 'pop', en realidad cambian la
matriz. Y as como con mtodos para textos, no tienes que
recordar todos, puedes recurrir a recordar sobre ellos buscando
informacin.
Primero, vamos a echar un vistazo a 'to_s' y 'join'. 'join' trabaja
tal como 'to_s' lo hace, excepto que este agrega un texto entre
los objetos de la matriz. Vamos a mirar un poco:
Cdigo:
alimentos = ['artichoke', 'brioche', 'caramel']
puts
puts
puts
puts
puts
puts
puts

alimentos
alimentos.to_s
alimentos.join(', ')
alimentos.join(' :) ') + ' 8)'

200.times do
puts []
end

Resultado:
artichoke
brioche
caramel
["artichoke", "brioche", "caramel"]

artichoke, brioche, caramel


artichoke :) brioche :) caramel 8)

Como puedes ver, 'puts' trata la matriz diferente a otros objetos:


solo llama 'puts' sobre cada uno de los objetos en la matriz.
Esto es porque 'puts' con una matriz vaca 200 veces no hace
nada; la matriz no apunta a nada; entonces no hay nada para
'puts'. (Hacer nada 200 veces contina siendo hacer nada)
Trata de usar 'puts' en una matriz conteniendo otras matrices;
hace lo que esperabas que hiciera?
Tambin, te habrs dado cuenta que dej fuera el texto vacio
cuando quise hacer 'puts' de una lnea en blanco? Esto hace lo
mismo.
Ahora vamos a echar un vistazo a 'push', 'pop', y 'last'. Los
mtodos 'push' y 'pop' son una suerte de mtodos opuestos
como lo son '+' y '-'. 'push' agrega un objeto al final de la matriz,
y 'pop' quita el ltimo objeto desde la matriz (y te dice que
objeto es). 'last' es similar a 'pop' en el sentido que te indica que
hay al final de la matriz, excepto que este deja la matriz. De
nuevo, 'push' y 'pop' en realidad cambian la matriz:
Cdigo:
favoritos = []
favoritos.push 'lluvia de rosas'
favoritos.push 'whisky en gatitos'
puts favoritos[0]
puts favoritos.last
puts favoritos.length
puts favoritos.pop
puts favoritos
puts favoritos.length

Resultado:

lluvia de rosas
whisky en gatitos
2
whisky en gatitos
lluvia de rosas
1

Algunas cosas por intentar

Escribe el programa del cual hablamos al principio de este


captulo. Consejo: Hay un hermoso mtodo para matrices el
cual te dar la version ordenada de una matriz: 'sort'. Usalo!

Escribe el programa sugerido anteriormente sin usar el mtodo


'sort'. Una gran parte de la programacin es la solucin de
problemas, entonces obtn toda la practica que puedas!

Reescribe tu programa Tabla de contenidos (en el captulo sobre


'mtodos'). Comienza el programa con una matriz conteniendo
toda la informacin de tu Tabla de Contenidos (captulo textos,
captulo nmeros, etc.). Entonces imprime la informacin desde
la matriz en una bien formada Tabla de Contenidos.
Hemos aprendido varios mtodos diferentes. Ahora es tiempo
de aprender como hacerlo por nosotros mismos.

Mtodos Propios
Como hemos visto anteriormente, los bucles e iteradores nos
permiten hacer lo mismo (o ejecutar el mismo cdigo) una y
otra vez. Sin embargo, a veces queremos hacer algo una
determinada cantidad de veces pero desde distintos lugares en

el programa. Por ejemplo, supongamos que estamos


escribiendo un programa que hace un cuestionario para un
estudiante de sicologa. De los estudiantes de sicologa que he
conocido y de los cuestionarios que me han dado, esto sera
algo similar a:
Cdigo:
puts
puts
puts
puts
puts
puts
puts
puts

'Hola, y gracias por tomarse el tiempo para'


'que me ayude con este experimento. Mi experimento'
'tiene que ver con tu gusto acerca de'
'la comida mexicana. Basta con pensar en la comida mexicana'
'y tratar de contestar todas las preguntas con honestidad,'
'ya sea con un "s" o un "no". Mi experimento'
'no tiene nada que ver con mojar la cama.'

# Preguntaremos, pero ignoraremos sus respuestas.


buenaRespuesta = false
while (not buenaRespuesta)
puts 'Te gusta comer tacos?'
respuesta = gets.chomp.downcase
if (respuesta == 'si' or respuesta == 'no')
buenaRespuesta = true
else
puts 'Por favor, responda "si" o "no".'
end
end
buenaRespuesta = false
while (not buenaRespuesta)
puts 'Te gusta comer burritos?'
respuesta = gets.chomp.downcase
if (respuesta == 'si' or respuesta == 'no')
buenaRespuesta = true
else
puts 'Por favor, responda "si" o "no".'
end
end
# Presta atencin a *esta* respuesta.
buenaRespuesta = false
while (not buenaRespuesta)
puts 'Mojas la cama?'
respuesta = gets.chomp.downcase

if (respuesta == 'si' or respuesta == 'no')


buenaRespuesta = true
if respuesta == 'si'
mojasLaCama = true
else
mojasLaCama = false
end
else
puts 'Por favor, responda "si" o "no".'
end
end
buenaRespuesta = false
while (not buenaRespuesta)
puts 'Te gusta comer chimichangas?'
respuesta = gets.chomp.downcase
if (respuesta == 'si' or respuesta == 'no')
buenaRespuesta = true
else
puts 'Por favor, responda "si" o "no".'
end
end
puts 'Solo una cuantas preguntas ms...'
buenaRespuesta = false
while (not buenaRespuesta)
puts 'Te gusta comer sopapillas?'
respuesta = gets.chomp.downcase
if (respuesta == 'si' or respuesta == 'no')
buenaRespuesta = true
else
puts 'Por favor, responda "si" o "no".'
end
end
# Preguntas otras cosas sobre la comida mexicana.
puts
puts
puts
puts
puts
puts
puts
puts
puts
puts
puts

'Interrogatorio:'
'Gracias por tomarse el tiempo para ayudar con'
'este experimento. De hecho, este experimento'
'no tiene nada que ver con la comida mexicana. Es'
'un experimento sobre mojar la cama. La comida mexicana'
'ah para atraparte con la guardia baja'
'con la esperanza de que respondera ms'
'honestamente. Gracias de nuevo.'
mojasLaCama

Resultado:
Hola, y gracias por tomarse el tiempo para
que me ayude con este experimento. Mi experimento
tiene que ver con tu gusto acerca de
la comida mexicana. Basta con pensar en la comida mexicana
y tratar de contestar todas las preguntas con honestidad,
ya sea con un "s" o un "no". Mi experimento
no tiene nada que ver con mojar la cama.
Te gusta comer tacos?
si
Te gusta comer burritos?
si
Mojas la cama?
de ninguna manera
Por favor, responda "si" o "no".
Mojas la cama?
NO
Te gusta comer chimichangas?
si
Solo una cuantas preguntas ms...
Te gusta comer sopapillas?
si
Interrogatorio:
Gracias por tomarse el tiempo para ayudar con
este experimento. De hecho, este experimento
no tiene nada que ver con la comida mexicana. Es
un experimento sobre mojar la cama. La comida mexicana
ah para atraparte con la guardia baja
con la esperanza de que respondera ms
honestamente. Gracias de nuevo.
false

Ese fue un programa bastante largo, con mucha repeticin.


(Todas las secciones de cdigo sobre las preguntas de comida
mexicana eran idnticas, y la pregunta sobre mojar la cama fue
la nica pregunta algo diferente). La repeticin es mala. Sin
embargo, no podemos transformar el cdigo en un gran bucle o
iterador, porque a veces queremos hacer algo entre las
preguntas. En situaciones como estas, es mejor escribir un
mtodo. Aqu est como:
def decirMu

puts 'muuuuuu...'
end

Uy... nuestro programa no hizo muuuuuu. Por qu no?, Porque


no le dijimos que lo hiciera. Le dijimos cmo hacer muuuuuu,
pero nunca le dijimos en realidad que lo haga. Intentemos otra
vez:
Cdigo:
def decirMu
puts 'muuuuuu...'
end
decirMu
decirMu
puts 'coin-coin'
decirMu
decirMu

Resultado:
muuuuuu...
muuuuuu...
coin-coin
muuuuuu...
muuuuuu...

Ah, mucho mejor. (En caso que no hables francs, eso fue un
pato francs en medio del programa. En Francia los patos dicen
coin-coin.)
Por lo tanto, definimos el mtodo de decirMu. (Nombres de los
mtodos, al igual que los nombres de variables, comienzan con
letras minsculas. Hay unas pocas excepciones, tales como +
o ==.) Pero los mtodos no siempre tienen que estar
asociados con objetos?. Bueno, s, y en este caso (como
sucede con puts y gets), el mtodo slo est asociado con el
objeto que representa la totalidad del programa. En el prximo
captulo veremos cmo agregar mtodos a otros objetos. Pero
primero ...

Parmetros del Mtodo


Habrs notado que algunos mtodos (como gets, to_s, reverse...)
solo pueden ser llamados en un objeto. Sin embargo, otros
mtodos (como + , - , puts...) toman los parmetros para decir
al objeto que hacer con el mtodo. Por ejemplo, no slo le dira
5+, verdad? Le ests pidiendo 5 que agregue, pero no le
ests diciendo lo que va a agregar.
Para agregar un parmetro a decirMu (digamos, el nmero de
muuuuuu), haramos lo siguiente:
Cdigo:
def decirMu numeroDeMus
puts 'muuuuuuu...'*numeroDeMus
end
decirMu 3
puts 'oink-oink'
decirMu # Esto debera dar un error porque falta el parmetro.

Resultado:

muuuuuuu...muuuuuuu...muuuuuuu...
oink-oink
in `decirMu': wrong number of arguments (0 for 1) (ArgumentError)

es una variable que apunta al parmetro que se


le ha pasado, lo voy a decir de nuevo, pero es un poco confuso:
numeroDeMus es una variable que apunta al parmetro pasado.
Por lo tanto, si digito decirMu 3, el parmetro es 3, y la variable
numeroDeMus apunta a 3.
numeroDeMus

Como puedes ver, el parmetro es ahora requerido. Despus


de todo, lo que decirMu hace es multiplicar 'muuuuuu... pero, si

no le dan un parmetro? Tu pobre computadora no tiene ni idea


de que hacer.
Si los objetos en Ruby son como los nombres en espaol, y los
mtodos son como los verbos, entonces se puede pensar en
parmetros como adverbios (como con decirMu, donde el
parmetro nos dice como se afecta decirMu) o a veces como
objetos directos (por ejemplo con puts, donde el parmetro es
lo que se muestra)

Variables Locales
En el siguiente programa hay dos variables:
Cdigo:
def duplicaEsto num
numeroVeces2 = num*2
puts num.to_s+' el doble es '+numeroVeces2.to_s
end
duplicaEsto 44

Resultado:

44 el doble es 88

Las variables son num y numeroVeces2. Los dos se encuentran


dentro del mtodo duplicaEsto. Estas (y todas las variables que
hemos visto hasta ahora) son las variables locales. Esto
significa que ellos viven dentro del mtodo y no pueden salir. Si
lo intentas obtendrs un error:
Cdigo:
def duplicaEsto num
numeroVeces2 = num*2

puts num.to_s+' el doble es '+numeroVeces2.to_s


end
duplicaEsto 44
puts numeroVeces2.to_s

Resultado:
44 el doble es 88
in `<main>': undefined local variable or method `numeroVeces2' for
main:Object (NameError)

Variable local no definida ... De hecho, nos hicieron definir esa


variable local, pero no es local donde trat de usarlo, es local
en el mtodo.
Esto podra ser un inconveniente, pero en realidad es bastante
bueno. Significa que no tienes acceso a las variables dentro de
los mtodos y tambin significa que ellos no tienen acceso a
tus variables y por lo tanto no pueden meter la pata:
Cdigo:
def pequenaMascota var
var = nil
puts 'HAHA! He malogrado tu variable!'
end
var = 'Tu ni siquiera puedes tocar mi variable!'
pequenaMascota var
puts var

Resultado:
HAHA! He malogrado tu variable!
Tu ni siquiera puedes tocar mi variable!

En realidad, hay dos variables en el programa que se llaman


var: uno en el interior de pequenaMascota y otro fuera de l.
Cuando llamamos a pequenaMascota var, nosotros en realidad
pasamos de un var a otro de manera que ambos estn
apuntando al mismo texto. Luego pequenaMascota apunt a su
propio var local a nil, pero que no hizo nada al var que est
fuera del mtodo.

Valores de Retorno
Puedes haber notado que algunos mtodos envan algo de
regreso cuando son llamados. Por ejemplo, gets retorna una
cadena (la cadena que escribiste), y el mtodo + en 5+3, (que
es en realidad 5.+(3)) devuelve 8. Los mtodos aritmticos para
los nmeros retornan nmeros y los mtodos aritmticos para
los textos devuelven textos.
Es importante entender la diferencia entre los mtodos que
devuelven un valor al mtodo que lo llam, y lo que el programa
muestra en la pantalla como hace puts. Ten en cuenta que 5+3
retorna 8, cosa que no hace la salida 8.
Entonces, qu es lo que hace puts al retornar? No nos import
antes, pero vamos a ver ahora:
Cdigo:
valorRetorno = puts 'Esto es lo que puts retorna:'
puts valorRetorno

Resultado:

Esto es lo que puts retorna:


cero

As que el primer puts retorn nil. A pesar de que no lo prueba,


el segundo puts tambin lo hizo, puts siempre retorna nil. Cada
mtodo tiene que devolver algo, incluso si el valor es solo nil.
Tmate un descanso rpido y escribe un programa para
averiguar lo que decirMu devuelve.
Te sorprendi? Bueno, as es como funciona: el valor devuelto

por un mtodo no es ms que la ltima lnea del mtodo. En el


caso de decirMu, esto significa que devuelve puts "muuuuuu... '*
Los numeroDeMus, lo cual es simplemente nil ya que puts
siempre devuelve nil. Si queremos que todos nuestros mtodos
devuelvan el texto 'submarino amarillo', slo tenemos que
ponerla al final de ellos:
Cdigo:
def decirMu numeroDeMus
puts 'muuuuuu...'*numeroDeMus
'submarino amarillo'
end
x = decirMu 2
puts x

Resultado:

muuuuuu... muuuuuuu...
submarino amarillo

Vamos a tratar con el experimento de sicologa otra vez, pero


esta vez vamos a escribir un mtodo que haga las preguntas
por nosotros. Se tendr que tomar la pregunta como un
parmetro, y devolver true si contestan que s, y false si
responden que no. (An cuando la mayora de veces ignoramos
la respuesta, sigue siendo una buena idea que nuestro mtodo
devuelva la respuesta. De esta manera se puede utilizar para la
pregunta de mojar la cama tambin.) Tambin voy a acortar el
saludo y el interrogatorio de manera que sea ms fcil de leer:
Cdigo:
def preguntar pregunta
buenarespuesta = false
while (not buenarespuesta)
puts pregunta
reply = gets.chomp.downcase
if (reply == 'si' or reply == 'no')
buenarespuesta = true

if reply == 'si'
answer = true
else
answer = false
end
else
puts 'Por favor, responder "si" o "no".'
end
end
answer # Esto es lo que retorna (`true` o `false`).
end
puts 'Hola, y gracias por...'
puts
preguntar 'Te gusta comer tacos?'
# Ignoramos la respuesta.
preguntar 'Te gusta comer burritos?'
mojasLaCama = preguntar 'Mojas la cama?' # Salvamos el valor
retornado.
preguntar 'Te gusta comer chimichangas?'
preguntar 'Te gusta comer sopapillas?'
preguntar 'Te gusta comer tamales?'
puts 'Solo unas preguntas mas...'
preguntar 'Te gusta beber horchata?'
preguntar 'Te gusta comer flautas?'
puts
puts 'Interrogatorio:'
puts 'Gracias por...'
puts
puts mojasLaCama

Resultado:
Te gusta comer tacos?
si
Te gusta comer burritos?
si
Mojas la cama?
de ninguna manera
Por favor, responder "si" o "no".
Mojas la cama?
NO
Te gusta comer chimichangas?
si
Te gusta comer sopapillas?
si
Te gusta comer tamales?
si

Solo unas preguntas mas...


Te gusta beber horchata?
si
Te gusta comer flautas?
si
Interrogatorio:
Gracias por...
false

No est mal, eh?. Hemos sido capaces de aadir ms


preguntas (y la adicin de preguntas ahora es fcil), y nuestro
programa es an ms corto!. Es una gran mejora - El sueo de
un programador perezoso.

Un ejemplo ms grande
Creo que otro mtodo como ejemplo podra ser til aqu.
Llamaremos a este numeroEnEspanol. Se llevar un nmero,
como 22, y devolver la versin en espaol de la misma (en
este caso el texto de 'veintids') Por ahora, vamos a trabajar
solamente con nmeros enteros entre 0 a 100.
(*NOTA:** Este mtodo utiliza un nuevo truco para retornar en
forma temprana en el mtodo usando return e introduce un
nuevo giro en las bifurcaciones: elsif. Debe quedar claro en el
contexto de cmo funcionan estos.)*
Cdigo:
def numeroEnEspanol numero
# Solo estamos considerando los nmeros de 0-100.
if numero < 0
return 'Por favor ingrese un numero mayor o igual a cero.'
end
if numero > 100
return 'Por favor ingrese un numero menor o igual a 100'

end
numeroDeTexto = '' # Esta es el texto que retorna.
# "izquierda" es cuanto del nmero an falta escribir.
# "escrito" es la parte que estamos escribiendo en estos
momentos.
# escrito y izquierda... lo captas? :)
izquierda = numero
escrito = izquierda/100
# Cuantos cientos faltan escribir?
izquierda = izquierda - escrito*100 # Restar estos cientos.
if escrito > 0
return 'cien'
end
escrito = izquierda/10
# Cuantas decenas faltan escribir?
izquierda = izquierda - escrito*10 # Restar las decenas.
if escrito > 0
if escrito == 1 # Ah-ah...
# No podemos escribir "diezidos" en lugar de "doce",
# hemos realizado una excepcin especial .
if izquierda == 0
numeroDeTexto = numeroDeTexto + 'diez'
elsif izquierda == 1
numeroDeTexto = numeroDeTexto + 'once'
elsif izquierda == 2
numeroDeTexto = numeroDeTexto + 'doce'
elsif izquierda == 3
numeroDeTexto = numeroDeTexto + 'trece'
elsif izquierda == 4
numeroDeTexto = numeroDeTexto + 'catorce'
elsif izquierda == 5
numeroDeTexto = numeroDeTexto + 'quince'
elsif izquierda == 6
numeroDeTexto = numeroDeTexto + 'dieciseis'
elsif izquierda == 7
numeroDeTexto = numeroDeTexto + 'diecisiete'
elsif izquierda == 8
numeroDeTexto = numeroDeTexto + 'dieciocho'
elsif izquierda == 9
numeroDeTexto = numeroDeTexto + 'diecinueve'
end
# Desde que ya tomamos el digito faltante,
# ya no tenemos nada que escribir.
izquierda = 0
elsif escrito == 2
# Como no podemos decir "veinteiuno",
# tenemos que eliminar la "e" final.

if izquierda == 0
numeroDeTexto = numeroDeTexto + 'veinte'
else
numeroDeTexto = numeroDeTexto + 'veint'
end
elsif escrito == 3
numeroDeTexto = numeroDeTexto + 'treinta'
elsif escrito == 4
numeroDeTexto = numeroDeTexto + 'cuartenta'
elsif escrito == 5
numeroDeTexto = numeroDeTexto + 'cincuenta'
elsif escrito == 6
numeroDeTexto = numeroDeTexto + 'sesenta'
elsif escrito == 7
numeroDeTexto = numeroDeTexto + 'setenta'
elsif escrito == 8
numeroDeTexto = numeroDeTexto + 'ochenta'
elsif escrito == 9
numeroDeTexto = numeroDeTexto + 'noventa'
end
if izquierda > 0
numeroDeTexto = numeroDeTexto + 'i'
end
end
escrito = izquierda # Cuanto falta para el nmero?
izquierda = 0
# Restar lo que falta.
if escrito > 0
if escrito == 1
numeroDeTexto =
elsif escrito == 2
numeroDeTexto =
elsif escrito == 3
numeroDeTexto =
elsif escrito == 4
numeroDeTexto =
elsif escrito == 5
numeroDeTexto =
elsif escrito == 6
numeroDeTexto =
elsif escrito == 7
numeroDeTexto =
elsif escrito == 8
numeroDeTexto =
elsif escrito == 9
numeroDeTexto =
end
end

numeroDeTexto + 'uno'
numeroDeTexto + 'dos'
numeroDeTexto + 'tres'
numeroDeTexto + 'cuatro'
numeroDeTexto + 'cinco'
numeroDeTexto + 'seis'
numeroDeTexto + 'siete'
numeroDeTexto + 'ocho'
numeroDeTexto + 'nueve'

if numeroDeTexto == ''
# La unica forma que "numeroDeTexto" este vacio es que
# "numero" sea 0.
return 'cero'
end
# Si numeroDeTexto os hasta hasta aqui es que tenemos un numero
# entre 0 y 100, por lo que debemos retornar "numeroDeTexto".
numeroDeTexto
end
puts
puts
puts
puts
puts
puts
puts
puts
puts

numeroEnEspanol( 0)
numeroEnEspanol( 9)
numeroEnEspanol( 10)
numeroEnEspanol( 21)
numeroEnEspanol( 17)
numeroEnEspanol( 32)
numeroEnEspanol( 88)
numeroEnEspanol( 99)
numeroEnEspanol(100)

Resultado:
cero
nueve
diez
veintiuno
diecisiete
treintaidos
ochentaiocho
noventainueve
cien

Bueno, sin duda hay algunas cosas acerca de este programa


que no me gustan. En primer lugar hay demasiada repeticin.
En segundo lugar, no se ocupa de los nmeros mayores de
100. En tercer lugar, hay muchos casos especiales,
demasiados returns. Veamos ahora algunas matrices y tratar de
limpiar un poco:
Cdigo:
def numeroEnEspanol numero
if numero < 0 # No numeros negativos
return 'Por favor ingresar un numero que nos ea negativo.'
end

if numero == 0
return 'cero'
end
# No mas casos especiales! No mas returns!
numeroDeTexto = '' # Esta es el texto que se retornara.
primeraPosicion = ['uno',
'dos',
'tres', 'cuatro',
'cinco',
'seis',
'siete',
'ocho', 'nueve']
segundaPosicion = ['diez',
'veinte', 'treinta', 'cuarenta',
'cincuenta',
'sesenta', 'setenta', 'ochenta', 'noventa']
entre11Y19 = ['once', 'doce', 'trece', 'catorce', 'quince',
'dieciseis', 'diecisiete', 'dieciocho', 'diecinueve']
entre21Y29 = ['veintiuno', 'veintidos', 'veintitres', 'veinticuatro',
'veinticinco',
'veintiseis', 'veintisiete', 'veintiiocho', 'veintinueve']
# "izquierda" es cuanto del numero aun falta escribir
# "escrito" es la parte que estamos escribiendo en este momento.
# escrito y izquierda... lo captas? :)
izquierda = numero
escrito = izquierda/100
# Cuantos cientos faltan escribir?
izquierda = izquierda - escrito*100 # La esta de estos cientos
if escrito > 0
# Ahora hacemos un pequeo truco:
cientos = numeroEnEspanol escrito
numeroDeTexto = numeroDeTexto + cientos + ' ciento'
# Eso se llama "recursividad". Entonces, Qu acabo de hacer?
# Le dije a este mtodo para llamarse a s mismo, pero con
"escrito" en vez de
# "numero". Recuerde que "escrito" es (por el momento) el nmero
de
# cientos que tenemos que escribir. Despus aadimos "hundred"
de "numeroDeTexto",
# aadimos la cadena 'cien' despus de l. As, por ejemplo, si
# se llam originalmente numeroEnEspanol con el 1999 (por lo que
"numero" = 1999),
# y luego en este momento "escrito" sera 19, y la "izquierda" sera
99.
# La ms perezoso que se puede hacer en ese momento es que
numeroEnEspanol
# escriba 'diecinueve' para nosotros, entonces escribimos 'cien',
# y luego el resto de numeroEnEspanol escribe "noventa y nueve".
if izquierda > 0
# So escribir 'dos ciencincuentaiuno'...

numeroDeTexto = numeroDeTexto + ' '


end
end
escrito = izquierda/10
# Cuantas decenas faltan escribir?
izquierda = izquierda - escrito*10 # Resta de estas decenas.
if escrito > 0
if ((escrito == 1) and (izquierda > 0))
# No podemos escribir "diez-dos" instead of "doce",
# hacemos una excepcin especial .
numeroDeTexto = numeroDeTexto + entre11Y19[izquierda-1]
# Es "-1" porque entre11Y19[3] ess 'catorce', no 'trece'.
# Ya que tomamos el digito que nos faltaba,
# no tenemos nada mas que escribir.
izquierda = 0
elsif ((escrito ==2 and (izquierda>0)))
# Similar para los veintipico
numeroDeTexto = numeroDeTexto + entre21Y29[izquierda-1]
izquierda = 0
else
numeroDeTexto = numeroDeTexto + segundaPosicion[escrito-1]
# Es "-1" porque segundaPosicion[3] es 'cuarenta', no 'treinta'.
end
if izquierda > 0
# No escribiremos 'sesentacuatro'...
numeroDeTexto = numeroDeTexto + 'i'
end
end
escrito = izquierda # Cuantos faltan?
izquierda = 0
# Restar lo que falta.
if escrito > 0
numeroDeTexto = numeroDeTexto + primeraPosicion[escrito-1]
# Es "-1" porque primeraPosicion[3] es 'cuatro', no 'tres'.
end
# Ahora solo retornamos "numeroDeTexto"...
numeroDeTexto
end
puts
puts
puts
puts
puts
puts

numeroEnEspanol(
numeroEnEspanol(
numeroEnEspanol(
numeroEnEspanol(
numeroEnEspanol(
numeroEnEspanol(

0)
9)
10)
11)
17)
32)

puts
puts
puts
puts
puts
puts
puts
puts

numeroEnEspanol( 88)
numeroEnEspanol( 99)
numeroEnEspanol(100)
numeroEnEspanol(101)
numeroEnEspanol(234)
numeroEnEspanol(3211)
numeroEnEspanol(999999)
numeroEnEspanol(1000000000000)

Resultado:
cero
nueve
diez
once
diecisiete
treintaidos
ochentaiocho
noventainueve
uno ciento
uno ciento uno
dos ciento treintaicuatro
treintaidos ciento once
noventainueve ciento noventainueve ciento noventainueve
uno ciento ciento ciento ciento ciento ciento

Ahhhh .... Eso est mucho, mucho mejor. El programa es


bastante denso, por lo que puse varios comentarios. Tambin
funciona con nmeros grandes ... aunque no tan bien como
cabra esperar. Por ejemplo, creo que ' un milln de millones '
sera un valor de retorno ms agradable para que el ltimo
nmero. De hecho, puedes hacer eso en este momento ...

Algunas cosas por intentar

Ampliar al numeroEnEspanol . En primer lugar, poner en miles.


Por lo tanto, debe devolver un mil en lugar de diez cien y diez mil
en lugar de cien cien .

Ampliar al numeroEnEspanol un poco ms. Ahora ponga en

millones, para que pueda obtener un milln en lugar de un mil


mil. A continuacin, pruebe a aadir miles de millones y
billones. Qu tan alto puede llegar?

Qu hay de tiempoDeMatrimonio? Deber trabajar casi como


numeroEnEspanol, excepto que se debe insertar la palabra "y"
por todo el lugar, volviendo las cosas como `mil novecientos
setenta y dos', o como se supone deben verse en las
invitaciones de la boda. Te dara ms ejemplos, pero yo no lo
entiendo completamente. Es posible que necesite ponerse en
contacto con un coordinador de bodas para que le ayude.

Las "Noventa y nueve botellas de cerveza ..." Usando


numeroEnEspanol y el viejo programa, escribir las letras de
esta cancin en forma correcta esta vez. Penalizar a tu
computador: hacer que se inicie en 9999. (No elegir un nmero
demasiado grande, ya que al escribir todo eso en la pantalla de
tu computador toma un buen tiempo. Cien mil botellas de
cerveza lleva tiempo;. Y si tienes que elegir un milln, te
estars castigando t mismo!
Felicitaciones! En este punto, usted es un programador de
verdad! Usted ha aprendido todo lo que necesita para construir
grandes programas desde cero. Si tienes ideas para los
programas que te gustara escribir para ti mismo, dame una!
Por supuesto, construir todo desde cero puede ser un proceso
bastante lento. Por qu gastar tiempo escribiendo cdigo que
alguien ms ya ha escrito? Quieres que tu programa envie un
correo electrnico? Te gustara guardar y cargar archivos en
tu computadora? Qu hay de la generacin de pginas web
para ver un tutorial en donde los ejemplos de cdigo son
automticamente ejecutados? ;) Ruby tiene muchos tipos de

objetos que podemos utilizar para ayudarnos a escribir mejores


programas y con mayor rapidez.

Clases
Hasta ahora hemos visto diferentes tipos o clases de objetos:
textos, enteros, flotantes, matrices, y algunos objetos
especiales (true, false y nil) de los cuales hablaremos ms
tarde. En Ruby, estas clases estn siempre en maysculas:
String, Integer, Float, Array ... etc. En general, si queremos crear
un nuevo objeto de una cierta clase, usamos new:
Cdigo:
a = Array.new + [12345] # Array agregado.
b = String.new + 'hello' # String agregado.
c = Time.new
puts 'a = '+a.to_s
puts 'b = '+b.to_s
puts 'c = '+c.to_s

Resultado:

a = [12345]
b = hello
c = 2012-06-01 12:52:06 -0500

Porque podemos crear matrices y textos usando [...] y ' ... '
respectivamente es que rara vez los creamos usando new.
(Aunque no es muy evidente en el ejemplo anterior, String.new
crea una cadena vaca y Array.new crea una matriz vaca)
Tambin, los nmeros son excepciones especiales: no se
puede crear un nmero entero con Integer.new . Slo tienes que
escribir el nmero entero.

La clase Time
Entonces, cul es la historia con la clase Time?. Los objetos
Time representan momentos en el tiempo. Usted puede sumar
(o restar) nmeros a (o desde) para obtener los nuevos
tiempos: la adicin de 1.5 a un tiempo hace un tiempo nuevo
segundo y medio ms tarde:
Cdigo:
hora = Time.new # El momento que se ejecut esta cdigo
hora2 = hora + 60 # Un minuto ms tarde.
puts hora
puts hora2

Resultado:
2012-06-01 12:55:49 -0500
2012-06-01 12:56:49 -0500

Tambin puedes obtener el tiempo para un momento especfico


utilizando Time.mktime:
Cdigo:
puts Time.mktime(2000, 1, 1)
# Y2K.
puts Time.mktime(1976, 8, 3, 10, 11) # Cuando naci Chris.

Resultado:
2000-01-01 00:00:00 -0500
1976-08-03 10:11:00 -0500

Nota: yo nac en el horario de verano del Pacfico (PDT).


Cuando se present el problema del ao 2000, sin embargo,
era hora estndar del Pacfico (PST), por lo menos para
nosotros los de la Costa Oeste. Los parntesis son para
agrupar los parmetros a mktime. Los parmetros adicionales
hacen ms preciso el tiempo obtenido.

Puedes comparar los tiempos usando los mtodos de


comparacin (un tiempo anterior es menos que un tiempo
posterior), y si se resta un tiempo de otro obtendrs el nmero
de segundos entre ellos. Juega un poco con l!

Algunas cosas para probar

Mil millones de segundos ... Descubre el segundo exacto en


que naciste (si puedes). Averigua cuando tendrs (o tal vez
cuando tuviste?) mil millones de segundos de edad, luego
marcalo en tu calendario.

Feliz cumpleaos! Pregunta en qu ao naci una persona,


luego el mes, y luego el da. Calcula la edad que tiene y dale
una gran NALGADA! por cada cumpleaos que ha tenido.

La clase Hash
Otra clase muy til es Hash. Los valores hash son muy
parecidos a las matrices: tienen un montn de ranuras que
pueden apuntar a objetos diferentes. Sin embargo, en una
matriz, las ranuras estn alineados en una fila y cada uno est
numerado (empezando de cero). En un hash, las ranuras no
estn en una fila (que es slo un tipo de mezcla), y se puede
utilizar cualquier objeto para hacer referencia a un espacio no
slo un nmero. Es bueno utilizar hashes cuando se tiene un
montn de cosas que no se desea perder de vista, pero que en
realidad no encajan en una lista ordenada. Por ejemplo los

colores que yo uso para las diferentes partes del cdigo con las
que he creado este tutorial:
Cdigo:
colorArray = [] # igual a Array.new
colorHash = {} # igual a Hash.new
colorArray[0]
= '#FF0000'
colorArray[1]
= '#008000'
colorArray[2]
= '#0000FF'
colorHash['textos '] = '#FF0000' # rojo
colorHash['numeros'] = '#008000' # verde
colorHash['claves '] = '#0000FF' # azul
colorArray.each do |color|
puts color
end
colorHash.each do |tipoCodigo, color|
puts tipoCodigo + ' : ' + color
end

Resultado:

#FF0000
#008000
#0000FF
textos : #FF0000
numeros : #008000
claves : #0000FF

Si utilizo una matriz, tengo que recordar que la ranura 0 es para


los textos, la ranura 1 es para los nmeros, etc, pero si puedo
usar un hash, es muy fcil! Ranura ' textos ' mantiene el color
de las cadenas, por supuesto. No hay nada que recordar.
Puedes haber notado que cuando se utiliza each los objetos en
el hash no vienen en el mismo orden en que los pusiste
adentro. (Al menos no lo hacan cuando escrib esto. Pueden
que lo hagan ahora... nunca se sabe con los hashes). Matrices
son para mantener las cosas en orden, no hashes.
Aunque la gente suele utilizar textos para nombrar las ranuras
de un hash, se puede utilizar cualquier tipo de objeto, incluso

las matrices y los hashes de otros (aunque yo no puedo pensar


en por qu querra hacer esto ...):
weirdHash = Hash.new
weirdHash[12] = 'monos'
weirdHash[[]] = 'el vaco'
weirdHash[Time.new] = 'ningun momento como el actual'

Hashes y matrices son buenos para cosas diferentes, depende


de ti decidir cul es el mejor para un problema particular.

Extendiendo las clases


Al final del ltimo captulo escribiste un mtodo para decir la
frase en espaol de un nmero entero. No era un mtodo de
nmero entero, sin embargo; fue slo un mtodo genrico de
un "programa". No sera agradable si pudieras escribir algo
como 22.to_esp en lugar de numeroEspanol 22?. He aqu cmo
haras eso:
Cdigo:
class Integer
def to_esp
if self == 5
espanol = 'cinco'
else
espanol = 'cincuenta y ocho'
end
espanol
end
end
# Mejor probarlo en un par de nmeros...
puts 5.to_esp
puts 58.to_esp

Resultado:

cinco
cincuenta y ocho

Bueno, lo he probado y parece que funciona. ;)


Por lo tanto, definimos un mtodo del nmero entero
ingresando en la clase Integer, definiendo el mtodo all y
saliendo luego. Ahora todos los nmeros enteros tienen este
(algo incompleto) mtodo. De hecho, si no te gusta la forma en
que el mtodo to_s trabaja, lo podras definir en gran parte de la
misma manera ... pero yo no lo recomiendo! Lo mejor es dejar
los viejos mtodos y hacer otros nuevos cuando se quiere
hacer algo nuevo.
As que ... confundido? Permiteme explayarme ms en ese
ltimo programa. Hasta ahora, cada vez que ejecutabas
cualquier cdigo o cualquier otro mtodo definido se haca por
omisin en el "programa" del objeto. En nuestro ltimo
programa, dejamos el objeto por primera vez y nos fuimos a la
clase Integer. Se defini un mtodo all (lo que lo convierte en
un mtodo de nmero entero) y que todos los nmeros enteros
pueden utilizar. Dentro de ese mtodo se utiliza self para
referirse al objeto (el entero) utilizando el mtodo.

Creando clases
Hemos visto diferentes clases de objetos. Sin embargo, es fcil
llegar a los tipos de objetos que Ruby no tiene. Por suerte, la
creacin de una nueva clase es tan fcil como la ampliacin de
una antigua. Digamos que hemos querido hacer algunos dados
en Ruby. As es como podemos hacer la clase Dado:

Cdigo:
class Dado
def roll
1 + rand(6)
end
end
# Vamos a crear un par de dados...
dados = [Dado.new, Dado.new]
# ...y hacerlos rodar.
dados.each do |dado|
puts dado.roll
end

Resultado:
3
4

(Si se ha saltado la seccin de nmeros aleatorios, rand(6) slo


da un nmero aleatorio entre 0 y 5 .) Y eso es todo! Nuestro
propios objetos. Tira los dados un par de veces (con el botn
de recarga) y mira lo que aparece.
Podemos definir todo tipo de mtodos para los objetos ... pero
hay algo que falta. Trabajar con estos objetos se parece mucho
a la programacin antes de aprender acerca de las variables.
Mira los dados!, por ejemplo. Podemos rodarlos y cada vez
nos dan nmeros diferentes. Pero si quera guardar alguno de
estos nmeros habra que crear una variable que apunte al
nmero. Parece que cualquier dado decente debe ser capaz de
tener un nmero, y que rodando el dado nuevamente el nmero
debe cambiar. Si hacemos un seguimiento del dado debemos
tener tambin un registro del nmero mostrado.
Sin embargo, si tratamos de guardar el nmero que sali en
una variable (local) roll habr desaparecido tan pronto como roll

haya terminado. Tenemos que guardar el nmero en un tipo


diferente de variable.

Variables de instancia
Normalmente cuando queremos hablar de un texto, nos
limitaremos a llamar a un texto. Sin embargo, tambin podra
llamar un objeto de texto. Sin embargo, los programadores
podran llamar una instancia de la clase String, pero esto es
slo una manera de representar a texto. Una instancia de una
clase es slo un objeto de esa clase.
Por lo tanto las variables de instancia son variables de un
objeto. Las variables locales de un mtodo viven hasta que el
mtodo ha terminado. Las variables de instancia de un objeto,
por otro lado, duran tanto como el objeto. Para diferenciar las
variables de instancia de las variables locales, ellos tienen @
delante de sus nombres:
Cdigo:
class Dado
def rodar
@numeroMostrado = 1 + rand(6)
end
def mostrar
@numeroMostrado
end
end
dado = Dado.new
dado.rodar
puts dado.mostrar

puts dado.mostrar
dado.rodar
puts dado.mostrar
puts dado.mostrar

Resultado:
1
1
5
5

Muy bien!. rodar rueda el dado y mostrar nos dice el nmero


que muestra. Sin embargo, que pasa si tratamos de mostrar lo
que exista antes de rodar el dado (antes de que lo hayamos
guardado en @numeroMostrado)
Cdigo:
class Dado
def rodar
@nummeroMostrado = 1 + rand(6)
end
def mostrar
@numeroMostrado
end
end
# Ya que no voy a usar este dado de nuevo,
# No es necesario guardarlo en una variable.
puts Dado.new.mostrar

Resultado:
nil

Hmmm ... bueno, al menos no nos muestra un error. An as,


no tiene mucho sentido para un dado "no rodado" mostrar nil o
lo que sea que se supone que significa. Sera bueno si
pudiramos dar un valor cuando nuestro objeto Dado es
creado. Para esto esta initialize:
Cdigo:

class Dado
def initialize
# Voy a tirar el dado, a pesar de que
# podria hacer otra cosa si quisieramos
rodar
end
def rodar
@numeroMostrado = 1 + rand(6)
end
def mostrar
@numeroMostrado
end
end
puts Dado.new.mostrar

Resultado:
6

Cuando se crea un objeto, su mtodo initialize (si se ha definido


uno) siempre es llamado. Nuestros dados son casi perfectos.
La nica cosa que podra hacer falta es una manera de decirle
que lado del dado debe mostrar... Por qu no escribir un
mtodo timo que hace justamente eso! Vuelve cuando hayas
terminado (y que haya funcionado por supuesto). Asegrese de
que nadie pueda obtener un 7 con el dado!
Hay varios temas interesante que apenas hemos revisado. Es
difcil, sin embargo te voy a dar otro ejemplo ms interesante.
Digamos que queremos hacer una mascota virtual sencilla, un
dragn beb. Como la mayora de los bebs debe ser capaz de
comer, dormir y hacer sus necesidades, lo que significa que
tendremos que ser capaces de darle de comer, de ponerlo en la
cama y llevarlo a pasear. Internamente, nuestro dragn tendr
que realizar una verificacin de si tiene hambre, est cansado o
tiene que ir al bao pero no vamos a ser capaces de ver su
estado cuando nos relacionamos con nuestro dragn al igual

que no se puede preguntar a un beb humano, "Tienes


hambre?". Tambin vamos a aadir algunas otras maneras
divertidas de interactuar con nuestro dragn beb y cuando
nace le daremos un nombre. (Lo que sea que pasen al mtodo
new al mtodo initialize). Muy bien, continuemos:
Cdigo:
class Dragon
def initialize nombre
@nombre = nombre
@dormido = false
@panzaLlena
= 10 # Esta lleno.
@intestinoLleno = 0 # No necesita ir.
puts @nombre + ' nace.'
end
def alimentar
puts 'Alimentas a ' + @nombre + '.'
@panzaLlena = 10
pasoDelTiempo
end
def caminar
puts 'Haces caminar a ' + @nombre + '.'
@intestinoLleno = 0
pasoDelTiempo
end
def dormir
puts 'Colocas a ' + @nombre + ' en la cama.'
@dormido = true
3.times do
if @dormido
pasoDelTiempo
end
if @dormido
puts @nombre + ' ronca, llenando el cuarto con humo.'
end
end
if @dormido
@dormido = false
puts @nombre + ' despierta lentamente.'
end

end
def lanzar
puts 'Lanzas a ' + @nombre + ' en el aire.'
puts 'Sonrie, sus cejas se mueven.'
pasoDelTiempo
end
def acunar
puts 'Acunas a ' + @nombre + ' suavemente.'
@dormido = true
puts 'Rapidamente se queda dormido...'
pasoDelTiempo
if @dormido
@dormido = false
puts '...pero despierta cuando te detienes.'
end
end
private
# "private" significa que los metodos definidos aqui son
# metodos internos al objeto. (Puedes alimentar a
# tu dragon, pero no puedes preguntar si esta hambriento.)
def hambriento?
# Los nombres de los metodos pueden terminar en "?".
# Generalmente, hacemos esto si el mtodo debe
# devolver verdadero o falso, como esto:
@panzaLlena <= 2
end
def ganas?
@intestinoLleno >= 8
end
def pasoDelTiempo
if @panzaLlena > 0
# Mueve el alimento del vientre al intestino.
@panzaLlena
= @panzaLlena
-1
@intestinoLleno = @intestinoLleno + 1
else # Nuestro dragon esta hambriento!
if @dormido
@dormido = false
puts 'Se despierta de repente!'
end
puts '' + @nombre + ' esta hambriento! En su desesperacion, te
COMIO!'
exit # Sale del programa.
end

if @intestinoLleno >= 10
@intestinoLleno = 0
puts 'Uy! ' + @nombre + ' tuvo un accidente...'
end
if hambriento?
if @dormido
@dormido = false
puts 'Se despierta de repente!'
end
puts 'El estomago de ' + @nombre + 'retumba...'
end
if ganas?
if @dormido
@dormido = false
puts 'Se despierta de repente!'
end
puts @nombre + ' hace la danza del bao...'
end
end
end
mascota = Dragon.new 'Norbert'
mascota.alimentar
mascota.lanzar
mascota.caminar
mascota.dormir
mascota.acunar
mascota.dormir
mascota.dormir
mascota.dormir
mascota.dormir

Resultado:
Norbert nace.
Alimentas a Norbert.
Lanzas a Norbert en el aire.
Sonrie, sus cejas se mueven.
Haces caminar a Norbert.
Colocas a Norbert en la cama.
Norbert ronca, llenando el cuarto con humo.
Norbert ronca, llenando el cuarto con humo.
Norbert ronca, llenando el cuarto con humo.
Norbert despierta lentamente.
Acunas a Norbert suavemente.
Rapidamente se queda dormido...

...pero despierta cuando te detienes.


Colocas a Norbert en la cama.
Se despierta de repente!
El estomago de Norbertretumba...
Colocas a Norbert en la cama.
Se despierta de repente!
El estomago de Norbertretumba...
Colocas a Norbert en la cama.
Se despierta de repente!
El estomago de Norbertretumba...
Norbert hace la danza del bao...
Colocas a Norbert en la cama.
Se despierta de repente!
Norbert esta hambriento! En su desesperacion, te COMIO!

Ouau! Por supuesto, sera mejor si fuese un programa


interactivo, pero puedes modificarlo. Yo slo estaba tratando de
mostrarte las partes relacionadas directamente con la creacin
de una nueva clase de dragn.
Vimos algunas cosas nuevas en ese ejemplo. La primera es
simple: exit termina el programa en ese mismo momento. La
segunda es la palabra private, que pusimos en la definicin de
nuestra clase. Podra haberlos mantenido afuera, pero yo
quera reforzar la idea de que hay ciertos mtodos que hacen
cosas que puede hacer un dragn y otros que simplemente se
establecen dentro el dragn. Usted puede pensar en ellos
como "bajo el cap": a menos que seas un mecnico de
automviles todo lo que necesitas saber es el pedal del
acelerador, el pedal del freno y el volante. Un programador
puede llamar a esto interfaz pblica del automvil. Sin
embargo, cmo saber cuando la bolsa de aire se activar es
algo interno del automvil, el usuario tpico (el conductor) no
tiene por qu saberlo.
En realidad, para un ejemplo ms concreto en ese sentido
vamos a hablar sobre cmo se podra representar un coche en
un videojuego (que pasa a ser mi lnea de trabajo). En primer
lugar, tienes que decidir como deseas que tu interfaz pblica se

parezca, es decir, los mtodos de la gente debera ser capaz de


llamar por cada uno de los objetos de su coche. Bueno, tienes
que ser capaz de empujar el pedal del acelerador y el pedal de
freno, pero que tambin tienes que ser capaz de especificar lo
fuerte que ests empujando el pedal. (Hay una gran diferencia
entre pisar y golpear) Tambin tendras que ser capaz de dirigir
el timn, y otra vez, tendras que ser capaz de decir lo mucho
que ests moviendo la rueda del timn. Supongo que se podra
ir ms all y aadir un embrague, direccionales, lanzacohetes,
cmara de post-combustin, condensador de flujo, etc ..
depende del tipo de juego que ests haciendo.
Internamente al objeto coche, sin embargo, tendramos que
hacer mucho ms cosas; otras cosas que necesita un coche
son una velocidad, una direccin y una posicin (que son las
cosas ms bsicas). Estos atributos se modificaran pulsando
sobre el gas o los pedales de freno y girando la rueda, pero el
usuario no sera capaz de establecer la posicin directamente
(que sera como una deformacin). Usted tambin podra
patinar o daar si se ha volcado y as sucesivamente. Todo
esto sera interno a su objeto coche.

Algunas cosas por intentar

Hacer una clase arbolNaranja. Deber tener un mtodo altura


que devuelve su altura y un mtodo paso365Dias que cuando se
le llama aumenta la edad del rbol en un ao. Cada ao crece
el rbol ms alto (mucho ms de lo que piensas que un naranjo
debe crecer en un ao), y despus de un cierto nmero de
aos (de nuevo, tu llamada) el rbol debe morir. En los

primeros aos el rbol no debe producir fruta, pero despus de


un tiempo debera hacerlo, y supongo que los rboles ms
viejos producen ms cada ao que los rboles ms jvenes ...
lo que pienses que tiene ms sentido. Y, por supuesto, t
debers ser capaz de contarNaranjas (que devuelve el nmero
de naranjas en el rbol), y tomarUnaNaranja (que reduce la
@numeroNaranjasen uno y devuelve un texto que te dice cmo la
naranja era deliciosa, o de lo contrario slo te dice que no hay
naranjas ms para elegir este ao) Asegrate que las naranjas
que no se recogen en un ao se caen antes del prximo ao.

Escribir un programa para que pueda interactuar con tu beb


dragn. Debers ser capaz de introducir comandos como
alimentar y caminar, y hacer que esos mtodos se llamen en tu
dragn. Por supuesto, ya que lo que ests ingresando son slo
textos, tendrs que tener algn tipo de mtodo de envo, donde
el programa revise los textos que se han ingresado y luego
llama al mtodo adecuado.
Y eso es casi todo lo que hay que hacer! Pero espera un
segundo ... Yo no he hablado de ninguna de esas clases para
hacer cosas como enviar un correo electrnico o guardar y
cargar archivos en el computador, o cmo crear ventanas y
botones, o los mundos en 3D, ni nada! Bueno, hay tantas
clases que pueden utilizar que no es posible mostrar a todos,
yo no conozco la mayora de ellos! Lo que puedo decir es que
para saber ms sobre ellos tienen que saber acerca de los que
deseas que el programa haga. Antes de terminar hay una
caracterstica ms de Ruby que debers conocer, algo que la
mayora de lenguajes de programacin no tiene pero sin las
cuales simplemente no podra vivir: bloques y procedimientos.

Bloques y
Procedimientos
Esta es definitivamente una de las mejores herramientas de
Ruby. Algunos lenguajes tienen esta herramienta, pienso que la
llamaran de otra forma (como closures), pero la mayora de los
ms populares no lo hacen, una pena.
Entonces qu es esto que es tan bueno? Esto tiene la
habilidad de tomar un bloque de cdigo (cdigo entre do y end)
y encapsularlo dentro de un objeto (llamado proc) y guardarlo
en una variable o pasarlo a un mtodo, y ejecutar el cdigo del
bloque donde te guste (ms de una vez, si quieres) Entonces
esto es como un tipo mtodo excepto que no est dentro de un
objeto (este bloque es un objeto), y puedes almacenarlo o
pasarlo como cualquier otro objeto. Es hora de un ejemplo:
Cdigo:
toast = Proc.new do
puts 'Aplausos!'
end
toast.call
toast.call
toast.call

Resultado:
Aplausos!
Aplausos!
Aplausos!

Entonces cre un proc (el cual pienso debera ser pronunciado


como "procedimiento") que contiene un bloque de cdigo, y
llam (called) el proc tres veces. Como puedes ver, esto es

como un mtodo.
En realidad, son ms parecidos a los mtodos que te he
mostrado, porque los bloques pueden tomar parmetros:
Cdigo:
teGusta = Proc.new do |algoRico|
puts 'Me gusta *realmente* el '+algoRico+'!'
end
teGusta.call 'chocolate'
teGusta.call 'ruby'

Resultado:

Me gusta *realmente* el chocolate!


Me gusta *realmente* el ruby!

Muy bien, entonces hemos visto que son los bloques y procs, y
como usarlos, pero cul es el punto? Porqu no utilizar
simplemente mtodos? Bueno, esto es porque hay ms cosas
que no podemos hacer con mtodos. En particular, no puedes
pasar mtodos a otros mtodos (pero puedes pasar procs
dentro de mtodos), y mtodos no pueden retornar otros
mtodos (pero ellos pueden retornar procs). Esto es
simplemente porque procs son objetos; los mtodos no son
objetos
(De hecho, es algo familiar para t? S, tu has visto bloques
antes... cuando aprendiste sobre iteradores. Pero vamos a
hablar un poco ms acerca de esto en breve)

Mtodos que reciben


Procedimientos

Cuando pasamos un proc en un mtodo podemos controlar


cmo o cuntas veces llamamos el proc. Por ejemplo, vamos a
decir que queremos hacer antes y despus de cierto cdigo
que se esta ejecutando:
Cdigo:
def hacerAlgoImportante unProc
puts 'Todo el mundo DETENGANSE! Tengo algo que hacer...'
unProc.call
puts 'A todos: Est hecho. Continuen con lo que estaban haciendo.'
end
decirHola = Proc.new do
puts 'hola'
end
decirAdios = Proc.new do
puts 'adios'
end
hacerAlgoImportante decirHola
hacerAlgoImportante decirAdios

Resultado:

Todo el mundo DETENGANSE! Tengo algo que hacer...


hola
A todos: Est hecho. Continuen con lo que estaban haciendo.'
Todo el mundo DETENGANSE! Tengo algo que hacer...
adios
A todos: Est hecho. Continuen con lo que estaban haciendo.'

Quiz esto no parezca muy fabuloso... pero lo es. :-) Es comn


en programacion tener requerimientos estrictos acerca de que
debe ser hecho y cuando. Si quieres salvar un archivo, por
ejemplo, tienes que abrir el archivo, escribir la informacion que
quieres que contenga y luego cerrar el archivo. El olvido de
cerrar el archivo puede traer malas consecuencias. Pero cada
vez que quieras salvar un archivo o cargar uno tienes que
hacer lo mismo: abrir el archivo, hacer lo que realmente quieres
hacer y luego cerrar el archivo. Esto es tedioso y fcil de
olvidar. En Ruby, guardar (o cargar) archivos trabaja en forma

similar al cdigo anterior, entonces no tienes que preocuparte


por nada ms que por lo que quieres guardar(o cargar). (En el
prximo capitulo mostrar donde encontrar informacin sobre
guardar y cargar archivos.)
Tambin puedes escribir mtodos que determinan cuantas
veces, o incluso si deben llamar a un proc. Aqu hay un mtodo
el cual podra llamar al proc la mitad de veces y otro el cual lo
llamar el doble de veces:
Cdigo:
def puedeHacerse unProc
if rand(2) == 0
unProc.call
end
end
def hacerDosVeces unProc
unProc.call
unProc.call
end
parpadeo = Proc.new do
puts '<parpadeo>'
end
mirada = Proc.new do
puts '<mirada>'
end
puedeHacerse parpadeo
puedeHacerse mirada
hacerDosVeces parpadeo
hacerDosVeces mirada

Resultado:

<mirada>
<parpadeo>
<parpadeo>
<mirada>
<mirada>

(Si ejecutas el programa un par de veces, vers que la salida

cambiar) Estos son algunos de los casos comunes de uso de


procs lo que le permite hacer cosas, utilizando simplemente
mtodos no podriamos hacerlo. Seguramente, podras escribir
un mtodo para que parpadee dos veces, pero no podras
escribir uno que haga algo dos veces!
Antes de continuar, vamos a ver un ltimo ejemplo. Los procs
que hemos visto son bastante similares. Es tiempo de ver algo
diferente, entonces vamos a ver cuanto un mtodo depende de
un proc pasado a este. Nuestro mtodo tomar algun objeto y
un proc, y llamar a este proc sobre este objeto. Si el proc
retorna falso, terminamos; en caso contrario llamaremos al proc
con el objeto. Continuaremos haciendo esto hasta que el proc
retorne falso (esto es mejor, o el programa finalizar con error).
El mtodo retornar el ltimo valor no falso retornado por el
proc.
Cdigo:
def hacerHastaQueSeaFalso primeraentrada, unProc
entrada = primeraentrada
salida = primeraentrada
while salida
entrada = salida
salida = unProc.call entrada
end
entrada
end
construirMatrizDeCuadrados = Proc.new do |array|
ultimonumero = array.last
if ultimonumero <= 0
false
else
array.pop
# Quitar el ltimo nmero...
array.push ultimonumero*ultimonumero # ...y reemplazar este
con el ltimo nmero elevado al cuadrado...
array.push ultimonumero-1
# ...seguido por un nmero
menor.

end
end
siempreFalso = Proc.new do |soloIgnorame|
false
end
puts hacerHastaQueSeaFalso([5],
construirMatrizDeCuadrados).inspect
puts hacerHastaQueSeaFalso('Estoy escribiendo esto a las 3:00 am;
alguien que lo finalice!', siempreFalso)

Resultado:
[25, 16, 9, 4, 1, 0]
Estoy escribiendo esto a las 3:00 am, alguien que lo finalice!

Est bien, este es un ejemplo bastante raro, debo admitirlo.


Pero esto muestra como acta diferente nuestro mtodo
cuando le damos diferentes procs.
El mtodo inspect es muy parecido a to_s , salvo que la cadena
que devuelve trata de mostrar el cdigo ruby para crear el
objeto que pas. Aqu se nos muestra toda la matriz devuelta
por nuestra primera llamada a haceHastaQueSeaFalso. Adems,
notamos que nosotros no procesamos el 0 al final de la matriz,
porque 0 al cuadrado sigue siendo 0 y por lo tanto no tena que
hacerse. Y puesto que siempreFalso era siempre
false,hacerHastaQueSeaFalso no hace nada la segunda vez que
se llama sino que retorna lo que se le pas.

Mtodos que retornan


Procedimientos
Una de las cosas interesantes que puedes hacer con procs es
crearlos en los mtodos y devolverlos. Esto permite realizar

cosas grandiosas de programacin (cosas con nombres


impresionantes, como lazy evaluation, estructuras de datos
infinitas y currying), pero el hecho es que casi nunca hago esto
en la prctica, ni puedo recordar haber visto a nadie hacer esto
en su cdigo. Creo que es el tipo de cosas que no suelen llegar
a tener que hacer en Ruby, o tal vez simplemente Ruby te
anima a buscar otras soluciones, yo no lo s. En cualquier
caso, slo voy a referirme a esto brevemente.
En este ejemplo, compose toma dos procs y devuelve un proc
nuevo que, cuando se le llama, llama al primer proc y pasa el
resultado en el segundo proc.
Cdigo:
def compone proc1, proc2
Proc.new do |x|
proc2.call(proc1.call(x))
end
end
cuadrado = Proc.new do |x|
x*x
end
doble = Proc.new do |x|
x+x
end
dobleYCuadrado = compone doble, cuadrado
cuadradoYDoble = compone cuadrado, doble
puts dobleYCuadrado.call(5)
puts cuadradoYDoble.call(5)
*Resultado:*
100
50

Ten en cuenta que la llamada a proc1 tena que estar dentro de


los parntesis para proc2 con el fin de que se haga en primer

lugar.

Pasando Bloques (no


Procedimientos) en los
Mtodos
Ok, esto es acadmicamente interesante pero tambin algo
difcil de usar. Gran parte del problema es que hay tres pasos
que se tienen que realizar (definir el mtodo, hacer el proc y
llamar al mtodo con el proc), parecera que solo debera haber
dos (definir el mtodo y pasar el bloque correcto dentro del
mtodo, sin necesidad de usar un proc) ya que la mayora de
las veces usted no desea utilizar el proc/bloque despus de
pasarlo al mtodo. Bueno, no lo sabes, Ruby tiene todo
resuelto por nosotros! De hecho, ya ha estabas haciendolo
cada vez que utilizabas iteradores.
Te mostrar primero un ejemplo rpido, y luego vamos a hablar
de ello.
Cdigo:
class Array
def cadaPar(&fueBloque_ahoraesProc)
esPar = true # Empezamos con "true" porque las matrices
comienzan con 0
self.each do |objeto|
if esPar
fueBloque_ahoraesProc.call objeto
end

esPar = (not esPar) # Cambiar de pares a impares o viceversa


end
end
end
['manzana', 'manzana podrida', 'cereza', 'durian'].cadaPar do |fruta|
puts 'Yum! Me encantan los pasteles de '+fruta+', no?'
end
# Recuerda,, estamos tratando de conseguir los numeros pares
# de la Matriz.
[1, 2, 3, 4, 5].cadaPar do |bolaImpar|
puts bolaImpar.to_s+' NO es un nmero par!'
end

Resultado:
Yum! Me encantan los pasteles de manzana, no?
Yum! Me encanta pasteles de cereza, no?
1 NO es un nmero par!
3 NO es un nmero par!
5 NO es un nmero par!

As que para pasar un bloque de cadaPar todo lo que tena que


hacer era pegar el bloque despus del mtodo. Puedes pasar
un bloque dentro de cualquier mtodo de esta manera, aunque
muchos mtodos simplemente ignorarn el bloque. Con el fin
de hacer que tu mtodo no ignore el bloque debes apoderarse
de l y convertirlo en un proc y poner el nombre del proc al final
de la lista de parmetros de tu mtodo precedida por el signo &.
As que esa parte es un poco difcil pero no demasiado y slo
tienes que hacer esto una vez (cuando se define el mtodo). A
continuacin, puedes utilizar el mtodo una y otra vez al igual
que los mtodos que reciben bloques como each y times.
(Recuerda que con 5.times hacemos ...?)
Si ests confundido, slo recuerda lo que cadaPar se supone
que debe hacer: llamar al bloque pasado con todos los dems
elementos de la matriz. Una vez que lo hayas escrito y funciona
no es necesario pensar en lo que est haciendo en realidad

internamente ("qu bloque se llama cuando?") De hecho, esto


es exactamente por lo que escribimos mtodos como ste: para
que no tengamos que pensar de nuevo en cmo trabajan. Nos
limitamos a usarlos.
Recuerdo una vez que quera ser capaz de medir la duracin
de distintas secciones de un programa. (Esto tambin se
conoce como profiling.) As que escrib un mtodo que toma la
hora antes de ejecutar el cdigo, ejecuta y luego toma la hora
al final para obtener la diferencia. No puedo encontrar el cdigo
en este momento, pero no lo necesito, ya que probablemente
fue algo como esto:
Cdigo:
def profile descripcionDeBloque, &bloque
inicioHora = Time.now
bloque.call
duracion = Time.now - inicioHora
puts descripcionDeBloque+': '+duracion.to_s+' segundos'
end
profile '25000 duplicaciones' do
numero = 1
25000.times do
numero = numero + numero
end
puts numero.to_s.length.to_s+' digitos' # El numero de digitos en
este numero ENORME.
end
profile 'contar hasta un millon' do
numero = 0
1000000.times do
numero = numero + 1
end
end

Resultado:
7526 digitos
25000 duplicaciones: 0.246768 segundos
contar hasta un millon: 0.90245 segundos

Qu sencillo! Qu elegante! Con ese pequeo mtodo puedo


fcilmente saber cuanto tiempo demora parte de cualquier
programa que quiero, solo ejecuto el cdigo en un bloque y se
lo envi a profile. Qu podra ser ms sencillo? En la mayora
de los lenguajes, yo tendra que aadir explcitamente el cdigo
de tiempo (lo que est dentro de profile) dentro de cada seccin
que deseo medir. En Ruby, sin embargo, tengo que mantener
todo en un solo lugar, y (ms importante) fuera de mi camino!

Algunas cosas por intentar

Reloj del Abuelo. Escriba un mtodo que toma un bloque y lo


llame una vez por cada hora que ha pasado hoy. De esta
manera, si paso al bloque do puts 'DONG!' end la campana
debera sonar (ms o menos) como un reloj de pndulo. Pon a
prueba tu mtodo con unas pocos bloques (incluyendo la que
acabo de darte). Sugerencia: Puede utilizar Time.now.hour para
obtener la hora actual. Sin embargo, este devuelve un nmero
entre 0 y 23, por lo que tendr que modificar los nmeros a fin
de obtener valores clsicos de un reloj de este tipo (1 al 12).

Program Logger. Escribir un mtodo llamado log, la cual toma


una cadena de un bloque y, por supuesto, el bloque. Al igual
que doSelfImportantly, deber puts una cadena diciendo que se
ha iniciado el bloque, y otra cadena diciendo que ha terminado
el bloque y tambin debe decir lo que el bloque retorn. Pon a

prueba tu mtodo mediante el envo de un bloque de cdigo.


En el interior del bloque, pon otra llamada a log pasando otro
bloque. (Esto se llama anidacin.) En otras palabras, su salida
debera ser algo como esto:
Listado:
A partir del "bloque externo" ...
A partir de "un bloque pequeo" ...
... "Algn pequeo bloque" termin, regreso: 5
A partir del "otro bloque" ...
... "Otro bloque", termin, regreso: me gusta la comida tailandesa!
... "Bloque exterior", termin, regreso: false

Mejores Logger. El resultado del ltimo logger fue un poco


difcil de leer y debera empeorar cuanto ms se use. Sera
mucho ms fcil de leer si se indenta las lneas en los bloques
interiores. Para ello, tendrs que llevar la cuenta de cun
profundamente ests anidado cada vez que el logger quiere
escribir algo. Para ello, utilice una variable global, una variable
que se puede ver en cualquier parte de tu cdigo. Para hacer
una variable global, slo precede a su nombre con el smbolo
$ , como los siguientes: $global, $nestingDepth y $bigTopPeeWee.
Al final, el logger debe generar un cdigo como este:
Listado:
A partir del "bloque exterior" ...
A partir de "un bloque pequeo" ...
A partir del "pequeito-minsculo bloque" ...
... "pequeito-minsculo bloque" termin, regreso: un montn de
amor
... "un bloque pequeo" termin, regreso: 42
A partir del "otro bloque" ...
... "otro bloque", termin, regreso: me encanta la comida india!
... "bloque exterior", termin, regreso: true

Bueno, eso es todo lo que vas a aprender de este tutorial.


Felicitaciones! Has aprendido un montn! Tal vez no tienes
ganas de recordar todo, o te has saltado unas partes ...
Realmente, eso est bien. La programacin no es sobre lo que

sabes, se trata de lo que puedes imaginar. Como siempre que


se sepa dnde encontrar las cosas que habas olvidado, lo
ests haciendo muy bien. Espero que no pienses que escrib
todo esto sin revisar estas cosas a cada minuto! Porque lo hice.
Yo tambin recib un montn de ayuda con el cdigo de los
ejemplos de este tutorial. Pero, dnde estaba yo buscando
estas cosas y donde yo pido ayuda?.
Te voy a ensear...

Despus de esta gua


Entonces, qu haremos ahora? Si tienes una pregunta, a
quin consultars? Que pasa si quieres un programa que abra
una pgina web, enve un correo electrnico, o redefina el
tamao de una foto digital? Bueno, hay muchos, muchos
lugares donde encontrar ayuda Ruby. Desafortunadamente,
esto es de poca ayuda, no? :-)
Para m, hay realmente solo tres lugares donde busco ayuda
sobre Ruby. Si es una pequea pregunta, y pienso que puedo
experimentar yo mismo para encontrar la respuesta, utilizo irb.
Si es una gran pregunta, busco por esto dentro de mis
herramientas. Y si no puedo darme cuenta por mi mismo,
entonces pregunto por ayuda en ruby-talk.

IRB: Ruby Interactivo


Si instalaste Ruby, entonces tienes instalado irb. Para usarlo,

solo ve a consola y tipea irb. Cuando estes en irb, puedes


tipear cualquier expresion ruby que quieras, y este te dir el
valor de esto. Tipea 1 + 2, y este te devolver 3. (Puedes darte
cuenta que no tienes que utilizar puts.) Esto es como una
calculadora Ruby gigante. Cuando finalizes, solo debes tipear
exit.
Hay un montn de cosas ademas para irb, pero puedes
aprender mucho ms probando esto.

El Pico: "Programming Ruby"


Absolutamente el libro Ruby a tener es "Programming Ruby 1.9,
The Pragmatic Programmer's Guide", por Dave Thomas, Chad
Fowler y Andrew Hunt (The Pragmatic Programmers). Mientras
que recomiendo tomar la tercera edicin de este excelente libro,
con todo lo ltimo cubierto.
Puedes encontrar todo lo que necesites de Ruby, desde lo
bsico a lo avanzado, en este libro. Es fcil de leer, fcil de
entender, es perfecto. Deseara que cada lenguaje tuviera un
libro de esta calidad. Al reverso del libro, encontrars una gran
seccin detallando cada mtodo en cada clase, explicandolo y
dando ejemplos. Me encanta este libro!
Hay algunos lugares donde puedes conseguir una versin ms
antigua (incluyendo el sitio mismo Pragmatic Programmers),
pero mi lugar favorito es en ruby-doc.org. Esta versin tiene una
linda tabla de contenidos a un costado, como tambin un
ndice. (ruby-doc.org tiene un montn ms de grandiosos
contenidos tambin, como para el Core API y biblioteca

estndar(Standard Library)... basicamente, documenta todo


Ruby. Chequealo aqu.)
Y porque es llamado "el pico"? Bueno, hay una imgen de un
pico en la tapa del libro. Es un nombre tonto, creo yo, pero
qued as.

Ruby-Talk: la lista de mails


Ruby
Aun teniendo irb y el pico, algunas veces sigues sin resolver
algo que necesitas. O quizs quieres saber si alguien ya hizo
algo de lo t ests intentando, para saber si puedes usar eso
en cambio. En estos casos, el lugar para esto es ruby-talk, la
lista de mails Ruby. Esta lleno de gente amigable, inteligente y
con ganas de ayudar. Para aprender ms de esto, o suscribirte,
mira aqu.
ADVERTENCIA: Hay muchos emails en esta lista de correos
cada da. Tuve que enviar directamente estos a diferentes
carpetas de mail para que no me molesten. Si no quieres
ocuparte de todos esos emails, pienso, no debes inscribirte. La
lista de mails es espejada en el grupo de noticias
comp.lang.ruby, y viceversa, entonces puedes ver los mensajes
ah. De igual manera, ves los mismos mensajes, pero en un
formato diferente.

Tim Toady
Algo que trat de mostrarte, lo cual seguramente podrs probar
pronto, es el concepto de TMTOWTDI (pronunciado como "Tim
Toady" en ingls for There's More Than One Way To Do It): Hay
Ms De Una Forma DE Hacer Esto.
Algunos te dirn que TMTOWTDI es maravillos mientras otros
puedan pensar algo diferente. No tengo fuertes sentimientos de
lascosas en general, pero pienso que esto es una terrible forma
de ensear a programar a alguin. (Como si aprender a
programar de una forma no fuera suficiente desafo y confuso!)
Sin embargo, ahora que te ests moviendose ms all de este
tutorial, vers mucha ms diversidad de cdigo. Por ejemplo,
pienso que al menos hay otras cinco formas de hacer un texto
(aparte de las que encierran un texto en comillas), y cada uno
de estos trabaja un poco diferente. Solo mostre lo ms simple.
Cuando hablamos de ramificacin, mostr el if, pero no mostr
el unless. Voy a dejar que te des cuenta por ti mismo en irb de
que se trata.
Otro lindo atajo que puedes usar con if, unless y while, es esta
linda versin de una lnea:
Cdigo:
# Estas lineas son de un programa que escribi para generar palabras
puts 'grobably combergearl kitatently thememberate' if 5 == 2**2 +
1**1
puts 'enlestrationshifter supposine follutify blace' unless 'Chris'.length
== 5

Resultado:
grobably combergearl kitatently thememberate

Y finalmente, hay otro camino para escribir mtodos la cual


toma bloques (no procs). Vimos la parte donde tomabamos el
bloque y lo convertamos dentro de un proc usando el truco
&block en la lista de parametros cuando defines una funcin.
Entonces, para llamar el bloque, solo usas block.call. Bueno,
hay una manera ms corta (aunque personalmente pienso que
es ms confuso). En lugar de esto:
Cdigo:
def hacerDosVeces(&block)
block.call
block.call
end
hacerDosVeces do
puts 'murditivent flavitemphan siresent litics'
end

Resultado:

murditivent flavitemphan siresent litics


murditivent flavitemphan siresent litics

...haces esto:
Cdigo:
def hacerDosVeces
yield
yield
end
hacerDosVeces do
puts 'buritiate mustripe lablic acticise'
end

Resultado:

buritiate mustripe lablic acticise


buritiate mustripe lablic acticise

No s... qu piensas? Quizs solo sea yo, pero... yield?! Si


esto fue algo como call_the_hidden_block o otra cosa ms, esto
tendra mucho ms sentido para mi. Mucha gente dice que yield

tiene sentido para ellos. Pero, supongo que es algo como


TMTOWTDI (Hay Ms De Una Forma De Hacer Esto), y eso es
todo: ellos hacen las cosas a su manera, y yo lo har a mi
manera.

Fin
Usa esto para lo bueno y no para lo malo. :-) Y si encuentras
este tutorial til (o confuso, o si encuentras un error), avsanos!

También podría gustarte