Hace mucho tiempo que
quería tomar contacto con un lenguaje de programación que ha tenido mucho auge
en Japón y en EEUU, y que en España está tímidamente haciéndose conocer. En los
últimos años, Ruby se está haciendo un hueco
importante entre los lenguajes de programación, especialmente para la Web,
gracias a su framework Ruby
On Rails (RoR).
Ruby es
un lenguaje de programación orientado a objetos, reflexivo e interpretado, con
una sintaxis inspirada en Python y en Perl, y con una implementación
de software libre. El intérprete de este lenguaje está disponible para varias
plataformas, tales como Windows, Linux o MacOS. Fue creado en 1995 por
Yukihiro "Matz" Matsumoto. La principal característica de este
lenguaje es que está pensado para la productividad.
Para empezar a realizar cosas con este lenguaje tenemos una "shell" o consola (como en Python), donde podemos probar
antes de generar el código final del programa. En el caso de Ruby, la consola se llama irb (Interface Ruby shell).
Lo más sencillo a probar es una simple operación matemática:
irb(main):001:0> 2+2
=>4
O un literal o cadena de caracteres, escrito entre comillas dobles
o simples:
irb(main):002:0>
"Soy Rafael"
=>"Soy
Rafael"
La diferencia con otros lenguajes de programación es que en Ruby todo es un objeto y, por tanto, se
puede acceder directamente a sus métodos y propiedades. Por ejemplo, en el
último ejemplo, hemos usado un literal, que es un objeto de tipo String. Por tanto, se puede
acceder a los métodos de dicho objeto:
irb(main):003:0>
"Soy Rafael".length
=>10
irb(main):004:0>
"Soy Rafael".reverse
=>"leafaR
yoS"
El método length retorna la longitud del literal,
mientras que el método reverse retorna el literal invertido.
El operador "+" permite sumar dos números, pero en el
caso de los literales, permite concatenar dos literales en 1:
irb(main):005:0> "Soy " +
"Rafael"
=>"Soy Rafael"
El operador "*" permite multiplicar dos números, pero en
el caso de los literales permite repetir dicho literal n veces:
irb(main):006:0> "Rafael"*3
=>"RafaelRafaelRafael"
Sin embargo, si se intenta realizar cualquier otro tipo de
operación matemática, ésta dará un error, ya que un literal tiene distinta
naturaleza de los números. Lo mismo ocurriría si se desea ejecutar un método de
literal para un número. Por ejemplo, lo siguiente daría un error:
irb(main):007:0>
"El resultado es: " + 2+2
=>
TypeError: can't convert Fixnum into String
Para poder llevar a cabo ésto será necesario que los valores sean
del mismo tipo, y para ello, disponemos de métodos de conversión o "casting":
irb(main):008:0>
"El resultado es: " + (2+2).to_s
=> "El resultado es: 4"
El método to_s (to string), permite convertir
un valor numérico a un literal. En el ejemplo se ha utilizado el paréntesis
para englobar el resultado del número.
El siguiente ejemplo realiza la operación inversa, es decir,
convierte un literal a un número para poder realizar la operación matemática:
irb(main):009:0>
20 + "4".to_i
=> "24"
El método to_i (to integer), convierte el
valor a un número de tipo entero.
Los siguientes ejemplos convierten un número en literal, y después
ejecutan un método específico para literales:
irb(main):010:0>
365.to_s.reverse
=> "563"
irb(main):011:0>
65535.to_s.length
=> 5
Ruby también
trata arrays, que son
colecciones de valores. Dichas colecciones se especifican encerrando entre
corchetes ([ ]) los valores que lo conforman. El siguiente ejemplo crea un array con una serie de valores
numéricos:
irb(main):012:0>
[20, 15, 45, 78, 27]
=> [20, 15, 45, 78, 27]
Los arrays también son objetos, y como tales,
también tienen métodos que realizan acciones:
irb(main):013:0>
[20, 15, 45, 27].max
=> 45
irb(main):014:0>
[20, 15, 45, 27].min
=> 15
irb(main):015:0>
[20, 15, 45, 27].length
=> 4
irb(main):016:0>
[20, 15, 45, 27].reverse
=> [27, 45, 15, 20]
El método max (maximum) retorna
el valor más alto del array.
El método min (minimum) retorna
el valor más bajo del array.
El método length retorna la longitud del array, es decir, el número de
valores que contiene. El método reverse retorna los valores del array en orden inverso.
Para facilitar el uso de los valores, Ruby permite almacenar los valores se
pueden almacenar variables, las cuales, serán automáticamente del tipo de los
valores que contienen. Las variables almacenan los valores bajo un nombre fácil
de recordar, y mediante el cual se refiere a dichos valores. Por ejemplo, si la
lista anterior se trata de una lista de préstamos, la cual se va a utilizar
para varias operaciones, lo mejor es almacenarlo en una variable que repetir la
lista constantemente:
irb(main):017:0>
prestamos
= [20, 15, 45, 27]
=> [20, 15, 45, 27]
irb(main):018:0>
print ticket[1]
20=> nil
irb(main):019:0>
prestamos.sort!
=> [15, 20, 27, 45]
irb(main):020:0>
prestamos.sort!.reverse
=> [45, 27, 20, 15]
En este ejemplo, se almacena la lista en la variable prestamos. Las siguientes
operaciones se realizan sobre la variable. En primer lugar, se visualiza el
valor que se encuentra en el array,
en la posición 1 (las posiciones dentro del array comienzan en 0 y terminan en longitud-1, y se accede a la
misma indicándolo entre corchetes). A continuación, el método sort! ordena
la lista de menor a mayor. Por último, ordena la lista y, a continuación, se
invierte el orden de la lista (ordenación de mayor a menor).
Un literal es un array de caracteres. Probemos lo siguiente:
irb(main):021:0>
texto = "en un lugar de la Mancha, de cuyo nombre no quiero acordarme"
=> "en un lugar de la Mancha, de cuyo nombre no quiero acordarme"
irb(main):022:0>
texto['lugar']='sitio'
=> "sitio"
irb(main):023:0>
print texto
en un sitio de la Mancha, de cuyo nombre no quiero acordarme=> nil
La variable texto contendrá un literal, que
en sí mismo en su array de caracteres. La segunda
sentencia, busca la subcadena 'lugar' dentro del array, y reemplaza su valor
por 'sitio'. La última
sentencia muestra el valor del literal con el resultado, en donde 'lugar' ha sido sustituido por 'sitio'.
El método include? nos permite consultar si una subcadena
se encuentra dentro del texto, retornando true (verdadero) o false (falso)
en caso afirmativo o negativo.
irb(main):024:0>
texto.include? "lugar"
=> false
irb(main):025:0>
texto.include? "Mancha"
=> true
Recordemos que, aunque sea un literal, seguimos tratando un array, y que algunos de los
métodos que estamos probando pueden servirnos para otro tipo de arrays. Así, el método include?
también puede aplicarse a nuestro array prestamos:
irb(main):026:0>
ticket.include? 20
=> true
irb(main):027:0>
ticket.include? 80
=> false
En el caso de los literales, hay métodos específicos, como, por
ejemplo, el poder convertir todos los caracteres del array a minúsculas (con el método downcase) o a mayúsculas (con el
método upcase):
irb(main):028:0>
texto.downcase
=> "en un sitio de la mancha, de cuyo nombre no quiero acordarme"
irb(main):029:0>
texto.upcase
=> "EN UN SITIO DE LA MANCHA, DE CUYO NOMBRE NO QUIERO ACORDARME"
Los arrays son un recurso valioso en la
programación con Ruby,
pero la complejidad de las necesidades reales con los datos nos van a exigir
algo más funcional y avanzado para un tratamiento secuencial y lineal de
colecciones de datos. Ruby provee un tipo de dato cuya
estructura es un diccionario y funciona como una tabla hash. Esto es, se define una
clave o valor único, y un valor, lo que facilita las búsquedas. Las siguientes
líneas definen y añaden valores a un diccionario, el cual es una colección de
libros, los cuales están catalogados por una valoración. En este caso, el
título del libro es la clave (valor único), y la catalogación es el valor (que
puede repetirse):
irb(main):030:0> libros = {}
=> {}
irb(main):031:0> libros["Don Quijote de la Mancha"] = :esplendido
=> :esplendido
irb(main):032:0>
libros["El Alquimista"] = :esplendido
=> :esplendido
irb(main):033:0>
libros["Millenium"] = :muy_bueno
=> :muy_bueno
irb(main):034:0>
libros["El angel caido"] = :mediocre
=> :mediocre
irb(main):035:0> libros
=> {"Don Quijote de la Mancha"=>:esplendido, "El Alquimista"=>:esplendido, "Millenium"=>:muy_bueno, "El angel caido"=>:mediocre}
A continuación, se consulta el tamaño del diccionario y se
consulta la valoración de un determinado libro:
irb(main):036:0> libros.length
=> 4
irb(main):037:0>
libros["Millenium"]
=> :muy_bueno
Para consultar las claves del diccionario, se utiliza el método key:
irb(main):037:0> libros.keys
=> ["Don Quijote de la Mancha", "El Alquimista", "Millenium", "El angel caido"]
Para consultar los valores del diccionario se utiliza el método values:
irb(main):038:0> libros.values
=> [:esplendido, :esplendido, :muy_bueno, :mediocre]
Conclusiones
Esta pequeña toma de contacto al lenguaje Ruby nos permite echar
un vistazo a los tipos de datos básicos que conforman el lenguaje, así como
vislumbrar la potencia que tiene al ser tratado todo como objetos, con sus
correspondientes métodos. Para conocer los métodos de cualquier objeto, basta
con ejecutar el método methods:
irb(main):038:0>
5.methods
=>
[:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**,:abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :integer?, :upto, :downto, :times, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, :singleton_method_added, :coerce, :i, :+@, :eql?, :quo, :remainder, :real?, :nonzero?, :step, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, :between?, :nil?, :=~, :!~, :hash, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :inspect, :methods,
:singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :__id__, :object_id, :to_enum, :enum_for, :require, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
irb(main):039:0>
"Soy Rafael".methods
=> [:<=>;, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop,:chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :__id__, :object_id, :to_enum, :enum_for, :require, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
Enlaces
Página oficial de Ruby: http://www.ruby-lang.org
Prueba Ruby desde el navegador: http://tryruby.org
Documentación de Ruby: http://www.ruby-lang.org/es/documentation