Claro, no necesito hacer el ritual de defender las 'ventajas de Ruby comparado con los lenguajes X, Y y Z' - la mayoría de la gente se da cuenta que cada lenguaje tiene un sabor único y un caracter propio - si escoges Python o Ruby para tu proyecto de Software Libre depende más de una afinidad particular que sientas individualmente por algún lenguaje que otro, y la disponibilidad de las facilidades de las librerías estándas, más que en arcanos apartados técnicos. ¡Así que disfruta el sabor único de Ruby!
Asumo que tu medio de desarrollo es Linux y que tienes Ruby instalado. Ruby es software libre, y no existen restricciones en su uso. Puedes obtenerlo de la página principal de Ruby .
Iniciaremos con el obligado 'Hello, World'.
% cat > hello.rb print "Hola Mundo\n" ^D % ruby hello.rb Hola Mundo %
La categorización es hecha basado en el primer caracter del nombre del identificador:
$ variable global
@ variable de instancia
a-z or '_' variable local
A-Z constante
Las dos 'pseudo-variables' son excepciones a la regla establecida arriba. Estas son 'self' y 'nil'
Ambas son llamadas como si fueran variables locales, ¡pero no lo son! veremos su significado real después.
Una variable global tiene su nombre iniciando con una $. Por tanto, puede ser referido en cualquier lugar del programa. Se debe notar que una variable global asume el valor 'nil' antes de inicializarla. Puedes probar esto con:
% ruby print $foo,"\n" $foo = 5 print $foo,"\n" ^D %El intérprete responde con:
nil 5Es posible para nosotros 'ligar' procedimientos a variables globales, los procedimientos son automáticamente invocados cuando las variables son cambiadas. ¡Más de esto después!
Algunos tipos especiales de variables globales formados con un sólo caracter que sigue al signo '$' son, como una colección, interpretados por Ruby como un sistema más amplio de variables (de sólo lectura). Algunos de ellos son dados abajo tanto con su significado.
Una variable local tiene su nombre inciiando con una letra minúscula o un '_'. A diferencia de las variables globales y las de instancia, estas no asumen el valor 'nul', pero tienen el comportamiento siguiente:
% ruby print foo ^DObtendrás este mensaje de error
"undefined local variable or method 'foo' for #(object...)".
El alcance de una variable local es confinado a uno de estos:
def foo(n) k = 2 * n print "\n",k,"\n" print defined? k,"\n" end foo 3 print defined? k,"\n" ^DLa salida es:
6 local-variable nil
En el ejemplo de arriba 'defined?' es un operador que checa si un argumento está definido o no. El resultado "local-variable" y "nil" (para indicar falso) debe hacerlo claro.
Cualquier nombre con caracteres siguiendo a una letra mayúscula es tratada como una constante. Pero los programadores de Ruby, para evitar confusiones usan nombres con todas las letras mayúsculas. Así que 'Foo' como también 'FOO' son constantes. Como en el caso de una variable local, una constante es definida por una sustitución y un acceso a una constante indefinida o la alteración de una constante definida causará un error. Verifícalo por ti mismo.
Las cadenas en ruby pueden ser con una comilla ('...') o con comillas dobles (".."). Pero ambas son diferentes. Usa las comillas dobles si la cadena contiene caracteres de escape. También los resultados de una evaluación son incluidos en expresiones contenidas en comillas por #{}. Observa los ejemplos:
print "\n"
print '\n'
print "\001","\n"
print '\001',"\n"
print "abcd #{5*3} efg","\n"
var = " abc "
print "1234#{var}567","\n"
^D
\n
\001
abcd 15 efg
1234abc567
Aprenderemos más sobre cadenas en las siguiente sección, arreglos. Esto es para incluir las características que son similares y las manejan tanto arreglos como cadenas.
Los arreglos pueden ser declarados usando '[]'. Una de las características de Ruby es que los arreglos son heterogéneos.
a = [1,2,"3"] print a,"\n" ^D
Ahora, si escribes un programa de Ruby para sumar todos los elementos del arreglo mostrados en el programa de arriba, obtendrás un error:
Error!!String cannot be coerced into Fixnum
El '3' en el arreglo es guardado como una cadena. Ahora, si se hace algo como esto:
a = [1,2,"3"] b = a[0] + a[1] + a[2].to_i print b,"\n" ^DEl programa se ejecutará sin errores. El agregado a a[2] i.e. '.to_i' es la conversión del contenido de a[2] a un entero. También puedes probar '.to_s'.
Operaciones como concatenación y repetición pueden ser hechas en arreglos.
a = [1,2,"3"] print a + ["foo","bar"] print a * 2 ^DObtenemos:
123foobar 123123
Es posible rebanar arreglos. Aquí hay algunos ejemplos:
a = [1,2,"3","foo","bar"] print a[0],"\n" print a[0,2],"\n" print a[0..3],"\n" print a[-2..2],"\n" print a[-3..-1],"\n"
Arreglos y cadenas son inter-convertibles. Un arreglo puede ser convertido a una cadena con 'join', y una cadena ser separada en un arreglo con 'split'.
a = [1,2,3]
print a[2],"\n"
a = a.join(":")
print a[2],"\n"
print a,"\n"
a = a.split(":")
print a[2],"\n"
print a,"\n"
^D
El Arreglo Asociativo es otra estructura importante de datos - también es llamada un 'hash' o un 'diccionario'. Es básicamente un mapeo de nombre-valor, como se muestra abajo:
h = {1 => 2, "2" => "4"}
print hash,"\n"
print hash[1],"\n"
print hash["2"],"\n"
print hash[5],"\n"
^D
¡Espero que estos resultados sean convincentes!
Vamos a escribir la función factorial. La definición matemática es:
n! = 1 (cuando n==0)
n! = n * (n-1)! (de otra manera)
En ruby esto puede ser escrito como:
def fact(n) if n == 0 1 else n * fact(n-1) end end print fact 4,"\n"You get 24.
Ruby ha sido llamado 'tipo Algol' debido a la repetida ocurrencia de 'end'. En esta llamada recursiva, puedes notar la ausencia de la sentencia de return (retorno). De hecho, el uso de return es permitido pero innecesario debido a que la función de ruby regresa la última expresión evaluada (¿no te suena esto un poco como Lisp? Si insistes, ¡claro que puedes hacer Lisp en Ruby!)
for i in 0..4 cuerpo-del-for end
Aquí i es la variable y 0..4 es el rango. En el caso de cadenas, puedes también escribir:
for i in "abc"
Intenta esto
i=0 while i < 10 print i+=1,"\n" end
Usamos la sentencia case para probar una secuencia de condiciones. Intenta esto.
i = 7 case i when 1,2..5 print "i en 2 a 5\n" when 6..10 print "i en 6 a 10\n" end ^D
Obtienes
i en 6 a 10
2..5 significa el rango incluyendo al 2 y al 5. Verifica si i se encuentra dentro del rango.
Esto puede ser aplicado a cadenas como se muestra abajo.
case 'abcdef' when 'aaa','bbb' print 'contiene aaa o bbb \n" when /def/ print "contiene def \n" end ^D contiene def
Date cuenta de la diagonal usada con "def". Es usada para denotar una expresión regular. Veremos esto más adelante.
La sentencia case mencionada arriba actualmente verifica en el rango (i in 2..5) como
(2..5) === i
El operación de relación '===' es usado por case para verificar por varias condiciones a la vez. '===' se interpreta como adecuado por ruby para el objeto que aparece en la condición when.
Por consiguiente en el ejemplo las cadenas iguales son probadas con el primer when y una expresión concuerda con el segundo when.
Ahora intentaremos usar el operador '===' con la estructura if (intenta implementar funciones como isalnum(), isalpha(), isnum(), etc.)
Tu código puede ser minimizado cuando tenemos que usar construcciones if y while para sentencias individuales: como mostramos abajo
i = 7 print "contenido en 5..10\n" if (5..10) === i print i-=1,"\n" while i > 0 ^D contenido en 5..10 6 5 4 3 2 1 0
Puedes a veces quere negar las condiciones de prueba. Un unless es un if negado, y un until es un while negado. Esto se te deja para que experimentes.
Hay cuatro maneras de interrumpir las sentencias de procesamiento de un ciclo desde adentro. Primero, como en C, break significa, escapar del ciclo completo. Segundo, next salta al inicio de la siguiente iteración del ciclo (corresponde a la sentencia continue en C). Tercer ruby tiene redo, el cual reinicia la iteración actual. El siguiente es el código en C que ilustra los significados de break, next, y redo:
while(condicion) {
label_redo:
goto label_next; /* "next" de ruby */
goto label_break; /* "break" de ruby */
goto label_redo; /* "redo" de ruby */
...
...
label_next:
}
label_break:
...
La sentencia return es de hecho la cuarta manera para salir de un ciclo desde adentro. De hecho return ocasiona la salida no sólo del ciclo sino también del método que contiene el ciclo.
Hiran Ramankutty