Está en la página 1de 10

William Viana y Andreu Belmonte 10

(’a’..’z’) representa las letras de la ’a’ a la ’z’

(1...5) representa los números del 1 al 4

El operador === sobre rangos sirve para comprobar si un valor está comprehendido en el rango, en caso
afirmativo devuelve true y en caso contrario false. El rango ha de estar a la izquierda del operador:
(1..10) === 5

2.3.5 Expresiones regulares


En Ruby la ausencia de valor se expresa con Sobre las expresiones regulares se han escrito libros enteros y dominarlas es casi más difícil que aprender Ruby
la constante nil. Si no se le asigna un valor a (talvez lo sea), pero son tremendamente útiles y los rubistas lo utilizan bastante, así que le dedicaremos algo de
una variable se le asigna por defecto nil tiempo. En Ruby las expresiones regulares son un tipo base como las cadenas o los números. Su utilidad es la
de encontrar palabras o patrones en un texto o comprobar que algo cumple un patrón. Las expresiones regulares
van delimitadas por barras. La manera más simple de utilizar una expresión regular para buscar una palabra en
una cadena sería la siguiente:
Cuando lo que buscas en una cadena es una texto.match(/Ruby/)
palabra es posible utilizar el operador [ ].
Nuestra búsqueda de la palabra Ruby en la El método match compruebo si se cumplen las condiciones de la expresión regular, si se cumplen devuelve un
cadena se podría haber hecho así: objeto de tipo MatchData, en caso contrario devuelve nil. En nuestro ejemplo match comprueba si en la
texto["Ruby"] cadena está presente la palabra Ruby.
Esto devuelve la cadena Ruby si ésta está pre- El operador =∼, sirve para el mismo propósito que match pero devuelve la posición del principio de la coinci-
sente en la variable texto y nil en caso con- dencia en caso de que se cumpla y nil en caso contrario. Además, en caso de coincidencia, asigna a las variables
trario. globales $‘,$& y $’ la parte de la cadena anterior a la coincidencia, la parte de la cadena coincidente y la parte
de la cadena posterior respectivamente.
i r b > " Programar en Ruby e s d i v e r t i d o " =~ /Ruby/
=> 13
i r b > p u t s " #{\$‘}<<#{\$&}>>#{\$ ’ } "
Programar en <<Ruby>> e s d i v e r t i d o
=> n i l
Lo cierto es que siempre les he tenido manía
a las expresiones regulares pero Ruby me ha Las expresiones regulares disponen de algunos caracteres y combinaciones de caracteres con un significado espe-
hecho que me reconcilie con ellas. Aún así, cial:
aún me cuesta utilizarlas
William Viana y Andreu Belmonte 11

Símbolo Significado
[a-z] Indica cualquier carácter entre la a y la z
[ab] Indica o una a o una b
\d Un dígito. Equivale a [0-9]
\w Una letra, un dígito o una barra baja. Equivale a [A-Za-z0-9]
\s Espacio en blanco [\t\r\n]
\b Límite de palabra
\D cualquier cosa escepto dígitos. Equivale a [ˆ\d]
\W es la negación de \w
\S es la negación de \s
\B es la negación de \b
. cualquier carácter
{n} Exactamente n veces lo que precede
{n,m} Al menos n y como máximo m de lo que precede
{n,} n o más de lo que precede
* Cero o más repeticiones de lo que precede
+ Una o más repeticiones de lo que precede
? Cero o una repetición de lo que precede
() Agrupamiento
ˆ La línea empieza por lo que va a continuación
$ La línea termina por lo que precede
i Puesto después de la última barra delimitadora hace que no se dis-
tinga mayúsculas de minúsculas
Algunas expresiones regulares:
/<\/?[^>]+>/ i #una e t i q u e t a de a p e r t u r a o c i e r r e en l e n g u a j e h t m l
/\d{8}[ −\ s ] ? [ a−z ] / i #un DNI
/\d+:\d+/ #una hora con f o r m a t o 0 0 : 0 0
/ . + ( \ . png ) $ / i #e l nombre de un a r c h i v o que t e r m i n a en png
/\/\∗.∗\∗\// #un c o m e n t a r i o en l e n g u a j e C
$
William Viana y Andreu Belmonte 12

2.3.6 Arrays

Los arrays son colecciones de valores agrupados alrededor de corchetes y separados por comas. Un array puede
contener valores de cualquier tipo y no necesariamente todos del mismo tipo. Como en la mayoría de lenguajes
de programación, se puede acceder a un elemento usando un índice dentro del operador [ ]. Los métodos de
repetición, concatenación y corte de las cadenas también sirven para los arrays. La diferencia importante con
otros lenguajes de programación es que si intentas acceder a un elemento que no está en el array no se produce
un error de índice fuera del rango sino que el array te devuelve el valor nil (ausencia de valor).
i r b > c a j o n = [ " c d s " , " l i b r e t a " , " b o l i g r a f o " , " l i b r o " , " c h i c l e pegado " ]
=> [ " c d s " , " l i b r e t a " , " b o l i g r a f o " , " l i b r o " , " c h i c l e pegado " ]
irb> cajon [ 4 ]
=> " c h i c l e pegado "
irb> cajon [ 2 . . 4 ]
=> [ " b o l i g r a f o " , " l i b r o " , " c h i c l e pegado " ]
irb> cajon [ 6 ]
=> n i l
irb> cajon [ 6 ] = " g a l l e t a "
=> " g a l l e t a "
irb> cajon
=> [ " c d s " , " l i b r e t a " , " b o l i g r a f o " , " l i b r o " , " c h i c l e pegado " , n i l , " g a l l e t a " ]
i r b > h a b i t a c i o n = %w/ e s c r i t o r i o o r d e n a d o r a r m a r i o e s t a n t e r i a /
=> [ " e s c r i t o r i o " , " o r d e n a d o r " , " a r m a r i o " , " e s t a n t e r i a " ]

El elemento de índice 8 no tenía ningún valor asignado, pero luego decido asignarle el valor “galleta”. Del índice
6 no he dicho nada pero Ruby ha puesto ahí un nil, en realidad es como si siempre hubieran estado ahí pero antes
no lo veíamos. La última línea es otra forma de inicializar un array de cadenas sin tener que estar escribiendo
las comillas y las comas, muy cómodo.

hola_fulanito2.rb
1 p r i n t " I n t r o d u c e nombre y a p e l l i d o s : "
2 nombre_completo = g e t s . s t r i p
3 nombres = nombre_completo . s p l i t
4 nombres . each { | nombre | nombre . c a p i t a l i z e ! }
5 nombre_completo = nombres . j o i n ( " " )
6 p u t s " Hola #{nombre_completo } ! "
William Viana y Andreu Belmonte 13

$ ruby h o l a _ f u l a n i t o 2 . rb
I n t r o d u c e nombre y a p e l l i d o s : s e n y o r sombrero
Hola Senyor Sombrero !
$

Ya sé que es un ejemplo muy estúpido pero sólo quería que vieras como convertir cadenas en arrays, arrays en
cadenas y que los arrays también tienen el iterador each.

2.3.7 Hashes

También llamados vectores asociativos o diccionarios, los hashes (los rubistas prefieren ese término) son como
los arrays pero no están ordenados y se accede a los elementos mediante una clave. Por tanto los hashes son una
colección de pares clave, valor rodeados por llaves dónde clave y valor están separados por los símbolos => y
pueden ser de cualquier tipo. Por supuesto no pueden haber claves repetidas. Si se intenta acceder a una clave
inexistente devuelve nil.
1 i n f o = { " nombre "=>" B r a u l i o da S i l v a " ,
2 " p r o f e s i o n "=>" F o t o g r a f o de p l a t o s combinados " ,
3 " a s p i r a c i o n "=>" Exponer en e l bar R e i n o l d s "
4 }
5
6 i n f o . each { | c l a v e , v a l o r | p u t s "#{c l a v e . c a p i t a l i z e } : #{v a l o r } " }

Un ejemplo estúpido más. A estas alturas creo que ya no merece ninguna explicación.
Ya hemos visto un poco más o menos todos los tipos base de Ruby pero con eso sólo no podemos hacer mucho.
Subamos un peldaño más.
3 Condicionando y repitiendo

3.1 Expresiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1.1 if y unless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1.2 case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2 Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.1 while y until . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.2 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

14
William Viana y Andreu Belmonte 15

Bueno, me he dado cuenta de que quizás estoy tratando de explicarlo todo como si no supieras programar. Si no
sabes programar te has equivocado de lugar. A partir de ahora vamos a ir un poco más rápido (o no me dará
tiempo de terminar el documento).
Este capítulo va de bucles y sentencias de control. En Ruby las sentencias de control son un poco diferentes de
los demás lenguajes y en seguida veremos por qué.

3.1 Expresiones
3.1.1 if y unless

En Ruby todo lo susceptible de devolver un valor lo hace. Por eso if, que en otros lenguajes decimos que es una
sentencia de control, en Ruby diremos que es una expresión ya que devuelve un valor. ¿Y qué valor devuelve?
Puedes llamarle a if como te dé la gana, me Pues el valor de la última línea que se ha evaluado
interesa que te acuerdes que devuelve un valor
1 d e j a r _ p a s a r = i f l i s t a . i n c l u d e ? B r a u l i o then : s i e l s e : no end
2 i f d e j a r _ p a s a r == : s i
3 p u t s " Pase por a q u i . "
4 e l s i f Braulio . ofrece_soborno ?
5 p u t s " Pase por a q u i c a b a l l e r o , y que t e n g a una a g r a d a b l e v e l a d a "
6 else
7 p u t s "No e s t a s en l a l i s t a , no e n t r a s . "
8 end

Creo que queda bastante claro la sintaxis del if, pero lo diré de palabra. Si lo quieres hacer todo en la misma
línea tan horrible como he hecho yo en la línea 1, has de incluir la palabra then después de la condición. Puedes
anidar condiciones con elsif y añadir al final un else opcionalmente. Al final has de incluir la palabra end para
finalizar el bloque. La identación es opcional.
La primera línea del ejemplo anterior es realmente horrible, no recomiendo que hagas nunca algo así. Ruby tiene
algo que puede hacer de esa línea mucho más elegante: los modificadores if. Esa misma línea se podría haber
escrito así
dejar_pasar = :si if lista.include? Braulio
Esa asignación se hará sólo si el pobre Braulio está en la dichosa lista. Si dejar_pasar no estaba inicializada y
Braulio no estaba en la lista entonces, como toda variable no inicializada, se le asignará nil.
William Viana y Andreu Belmonte 16

La expresión unless es la forma negada de if.


if foo != 0 equivale a unless foo == 0
Por último hay que recalcar una diferencia importante entre Ruby y otros lenguajes:

sorpresa.rb
1 foo = 0
2 i f foo
3 p u t s " Seguro que no t e e s p e r a b a s que s e i m p r i m i e r a e s t o "
4 else
5 p u t s "Y e s p e r a b a s que s e i m p r i m i e r a e s t o o t r o "
6 end

unless me parece un poco raro pero no sé El único caso en el que se ejecutaría el bloque de código del else sería cuando foo fuera igual a nil o a false.
por qué lo uso bastante, supongo que por la
novedad. 3.1.2 case

case es como el switch de C. Para quien no conoce el switch de C, es parecido a tener varios elsif anidados, pero
Está genial eso de escribir un manual, uno con una sintaxis más cómoda.
puede poner lo que le dé la gana con total lib-
ertad. Os lo recomiendo. precio_musica.rb
1 o p i n i o n _ p e r s o n a l = case precio_de_un_cd
2 when 0 . . . 5
3 " genial "
4 when 5 . . . 1 0
5 " razonable "
6 when 1 0 . . . 1 5
7 " e s p e r o que t e n g a un l i b r i t o c h u l o "
8 when 1 5 . . 2 0
9 " un poco caro , p e r o s i l l e v a dvd e s a c e p t a b l e "
10 else
11 " un abuso "
12 end

Se evalúa lo que va justo después del case y se compara usando el operador ===. Al igual que con el if si quieres
hacerlo todo en la misma línea has de incluir la palabra then, sino puedes omitirla.
William Viana y Andreu Belmonte 17

3.2 Bucles
3.2.1 while y until

El bucle while se ejecuta mientras se cumpla una condición y until mientras no se cumpla. Al igual que if y
unless, while y until se pueden usar como modificadores.

newpass.rb
1 opcion = 0
2 u n t i l o p c i o n == 2
3 p u t s " 1 − I n t r o d u c i r nuevo password "
4 puts " 2 − S a l i r "
5 opcion = 0
6 u n t i l ( 1 . . 2 ) === o p c i o n
7 print " Introduce opcion : "
8 o p c i o n = STDIN . g e t s . to_i
9 end
10 i f o p c i o n == 1
11 p r i n t " I n t r o d u c e nuevo password : "
12 password = STDIN . g e t s . r s t r i p
13 u n t i l password . match ( / ^ . { 8 , 1 5 } $ / )
14 p u t s " El password ha de t e n e r de 8 a 15 c a r a c t e r e s "
15 p r i n t " I n t r o d u c e nuevo password : "
16 password = STDIN . g e t s . r s t r i p
17 end
18 p u t s " Password a c t u a l i z a d o "
19 end
20 end

Bien, los ejemplos poco a poco los puedo hacer más interesantes. Si has llegado hasta aquí creo que ya eres capaz
de entender ese trozo de código sin que tenga que explicar nada (creo que incluso alguien que no hable Ruby
puede entenderlo).

3.2.2 for

El bucle for itera sobre colecciones al igual que hace el iterador each. Tiene una sintaxis muy parecida a Python:
William Viana y Andreu Belmonte 18

1 f o r e l e m e n t o in i t e r a b l e
2 ...
3 end

iterable es cualquier cosa sobre la que se pueda iterar (un rango, un array, una cadena, un diccionario), de hecho
Ruby traduce eso a algo como:
1 i t e r a b l e . each { | e l e m e n t o | ... }
4 New kids on the block

4.1 Métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.1.1 Cómo hacer bien un finger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2 Bloques e iteradores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.1 ¿Qué echan en el cine? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

19