viernes, septiembre 28, 2012

[viernes, septiembre 28, 2012] Ruby :: Métodos

Hemos visto diferentes métodos: puts, gets, etc. (¡intenta hacer una lista de todos los métodos que hemos visto hasta ahora! Hay diez de ellos, la respuesta está abajo), pero no hemos realmente hablado sobre que hacen los métodos. Sabemos que hacen, pero no lo que son.

Pero realmente, esto es lo que son: cosas que generan otras. Si los objetos (como las cadenas, los enteros o los flotantes) son los sujetos en el lenguaje Ruby, entonces los métodos son como los verbos. Y, justo como en el español, tú no puedes tener un verbo sin un sustantivo para hacer algo. Por ejemplo, tic-tac no es algo que sólo ocurre; un reloj (o algo) tiene que hacer esto. En español podemos decir: "El reloj hace tic-tac". En Ruby podemos decir clock.tick (asumiendo por supuesto que clock es un objeto Ruby). Los programadores suelen decir que estamos "invocando o llamando el método tick de clock" o también que invocamos o llamamos al "tick de clock".

Entonces, ¿has hecho la lista del primer párrafo? Bien. Bueno, estoy seguro que recordaras los métodos puts, gets, y chomp, dado que ya hablamos sobre ellos. Probablemente también recuerdas los métodos de conversión 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 aritmética ¡+, -, *, y /!

Así como cada verbo necesita un sustantivo, cada método necesita un objeto. Esto es generalmente fácil de ver e indicar: el objeto 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 métodos aritméticos. Como resulta, 5 + 5 es solo otra forma fácil de escribir 5.+ 5. Por ejemplo:

Código:

puts 'hola '.+ 'mundo'
puts (10.* 9).+ 9
Resultado:
hola mundo
99

Esto no se ve de la forma en la que nosotros comúnmente escribimos matemáticas, por lo que lo vamos a escribir siempre como ahora; sin embargo, es importante entender que realmente estas operaciones son también métodos.

Esto también nos da un profundo entendimiento de porque podemos hacer 'pig'*5 pero no podemos hacer 5*'pig': 'pig'*5 está diciendo a 'pig' que se multiplique 5 veces, pero 5*'pig' está diciendo a 5 que se multiplique 'pig' veces. 'pig' sabe como hacer 5 copias de si mismo y poner una detrás de otra; sin embargo, 5 será incapaz de hacer 'pig' copias de si mismo y sumarlos a todos juntos.

Y, por supuesto, continuaremos teniendo puts y gets para explicar. ¿Dónde están sus objetos? En español, puedes algunas veces dejar fuera el sustantivo; por ejemplo, si un villano grita "¡Muere!", el sustantivo implícito 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 contiene el objeto en el que estás. Todavía no sabemos si quiera como estar en un objeto, pero hasta que lo aprendamos, podemos decir que siempre vamos a estar en el gran objeto que es... ¡el programa entero! Y este objeto, el programa entero, tiene unos pocos métodos, que incluyen a puts y a gets. Lo que sucede es que no se puede en este caso usar self.loquesea directamente. Observa lo siguiente:

Código:
noPuedoCreerQueUnaVariableConNombreTanLargoContengaSoloUn3 = 3
puts noPuedoCreerQueUnaVariableConNombreTanLargoContengaSoloUn3
self.puts NoPuedoCreerQueUnaVariableConNombreTanLargoContengaSoloUn3
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 método es propiedad de un objeto, incluso si no tiene un punto enfrente de este. Si entiendes esto estás preparado.

Métodos imaginativos de las cadenas
Vamos a aprender unos pocos pero interesantes métodos. No tienes porque memorizar todos; puedes mirar esta pagina de nuevo si te olvidas de alguno. Yo sólo quiero mostrarte una pequeña parte de lo que se puede hacer con una cadena. De hecho, yo no recuerdo de memoria ni siquiera la mitad de los métodos para cadenas que se pueden usar; pero está bien, porque hay buenas páginas en internet que contienen todos los métodos existentes.

Realmente, tampoco quiero saber todo acerca de los métodos para cadenas; sino sería como tratar de conocer cada palabra en el diccionario. Puedo hablar español bien sin conocer cada una de las palabras del diccionario... ¿y no es ese realmente el objetivo del diccionario? ¡De hecho no tienes por qué conocer todo lo que hay en éste para decir que sabes español!

Entonces, nuestro primer método para cadenas es reverse, el cual nos da una version invertida de un texto:

Código:
var1 = 'parar'
var2 = 'subrayado'
var3 = 'Puedes pronunciar esta oración al reves?'
puts var1.reverse
puts var2.reverse
puts var3.reverse
puts var1
puts var2
puts var3
Resultado:
rarap
odayarbus
?sever la nóicaro atse raicnunorp sedeuP
parar
subrayado
Puedes pronunciar esta oración al reves?
Como puedes ver, reverse no revierte el orden de la cadena original; éste sólo hace una nueva versión de éste en orden inverso. Esto es porque var1 continua conteniendo 'parar' aún después de que invoquemos al reverse de var1.

Otro método para texto es length, el cual nos dice el número de caracteres (incluyendo espacios) que tiene una cadena:

Código:
puts 'Cuál es tu nombre completo?'
name = gets.chomp
puts '¿Sabes que hay ' + name.length + ' caracteres en tu nombre, ' + name + '?'
Resultado:
Cuál es tu nombre completo?
Christopher David Pine
#<TypeError: can't convert Fixnum into String>
¡¡Uhh!! Algo salió mal, y esto parece que ocurrió después la línea name = gets.chomp... ¿Puedes ver el problema? Fijate si puedes darte cuenta.

El problema es con length: esto te devuelve un número, pero nosotros queremos un texto. Esto es fácil, necesitamos solo agregar to_s (y cruzar nuestros dedos):

Código:
puts 'Cuál es tu nombre completo?'
name = gets.chomp
puts '¿Sabías que hay ' + name.length.to_s + ' caracteres en tu nombre, ' + name + '?'
Resultado:
Cuál es tu nombre completo?
Christopher David Pine
Sabías que hay 22 caracteres en tu nombre, Christopher David Pine
Hay que darse cuenta que este número es el número de caracteres en mi nombre, no el número de letras.

Hay también una serie de métodos para cadenas que juegan con las mayúsculas y las minúsculas: upcase cambia cada minúscula por mayúscula; swapcase cambia cada letra minúscula por mayúscula y viceversa; finalmente, capitalize es como downcase, excepto que esta cambia solo el primer carácter a mayúsculas (si es una letra).

Código:
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 estándar. Como puedes ver desde la linea puts ' a'.capitalize, el método capitalize sólo deja en mayúsculas el primer carácter, no la primera letra. También, como hemos visto antes, en todas estas llamadas a métodos, la variable letters permanece igual. Hay algunos métodos los cuales hacen cambios al contenido de los objetos asociados, pero no los hemos visto aún, y no lo haremos por algún tiempo.

El último tipo de métodos que veremos son los de formato visual. El primero es, center, que pone espacios al comienzo y final de la cadena para hacer que la cadena tenga un cierto tamaño y el texto original permanezca centrado. Entonces si quiero centrar las lineas de un poema, debería hacer algo como esto:

Código:
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.
Ser perezoso no es siempre algo malo en programación. Por ejemplo, fíjate como guardé el ancho del poema en la variable lineWidth.Esto supone que si entonces quiero regresar más tarde y hacer el poema más ancho, solo tengo que cambiar la variable al comienzo del programa, antes que en cada línea. Con un poema muy largo, esto podría ahorrarme un montón de tiempo. Este tipo de pereza es realmente una virtud en programación.

Los otros dos métodos 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 acción:

Código:
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 <--

1 comentario: