R: El método instance_methods devuelve un array que contiene los nombres de los métodos a los que responde el receptor. Incluye los métodos de las superclases y de los módulos mezclados.
instance_methods(nil) devuelve los métodos definidos en la clase del objeto.
R: Depende. Antes de la versión 1.5.2 de Ruby, el generador de números aleatórios tenía (por defecto) una semilla constante y por lo tanto producía la misma serie de números cada vez que se ejecutaba un programa. Si se necesitan comportamientos menos deterministas, hay que llamar a srand para establecer una semilla menos predecible.
Versiones más modernas tienen un comportamiento diferente. Si se llama a rand sin una llamada previa a srand, Ruby genera su propia semilla aleatória. Ejecuciones posteriores de un programa que no utiliza srand generarán secuencias diferentes de números aleatorios. Para obtener el antiguo y predecible comportamiento, hay que llamas a srand con una semilla constante.
R: Fixnum, true, nil y false esrán implementados como valores inmediatos. En los valores inmediatos, las variables contienen los objetos mismos no referencias a ellos.
Los métodos singleton no se pueden definir como objetos de este tipo. Dos Fixnum con el mismo valor siempre representan la misma instancia luego (por ejemplo) variables de instancia con el valor de "uno" están compartidas entre todas las instancia "uno" del sistema. Esto hace imposible definir un método singleton para una de ellas.
R: Primero las igualdades. nil y false son los dos únicos valores que se evalúan a falso en un contexto booleano.
Sin embargo, se tratan de instancias de clases diferentes (NilClass y FalseClass), y en cualquier otro lugar tienen comportamientos diferentes.
Se recomienda que los métodos de predicado (aquellos que terminan en una interrogación) devuelvan true o false. Aquellos que deban indicar un fallo deben devolver nil.
R:
open("example","r+").readline.each_with_index{|l, i| l[0,0] = (i + 1).to_s + ": " } |
io = open("example","r+") ary = io.readlines ary.each_with_index([l, i| = (i + 1).to_s + ": "} io.rewind io.print ary io.close |
R: Utilizando la opción de línea de comandos -i o con la variable predefinida $-i, se puede leer un fichero y reemplazarlo.
El código del punto anterior, que añade los números de línea a un fichero, sería probablemente mejor utilizando esta técnica.
$ ruby -i -ne 'print "#$.: #$_"' example |
R: Esta pieza de código no funciona correctamente:
open('file','w').print "Este es un fichero.\n" system 'cp file newfile' |
Este problema no aparece si se cierra el fichero antes de realizar la copia.
f = open('file','w') f.print "Este es un fichero.\n" f.close system 'cp file newfile' |
R: A medida que se lee un fichero, Ruby incrementa el contador de número de líneas de la variable global $.. Disponible también a través del atributo lineno de un objeto File.
La variable constante ARGF es un objeto de tipo fichero que se puede utilizar para leer todos los ficheros de entrada indicados en la líena de comandos (o de la entrada estándar si no hay ficheros). ARGF se utiliza implicitamente en código como el siguiente:
while gets print $_ end |
ARGF.file.lineno |
R: Si se intenta los siguiente, no funciona.
f = open '|less', 'w' f.print "abc\n" |
R: Un objeto File que ya no está referenciado pasa a estar a disposición del recolector de basura. El fichero se cerrará automáticamente cuando es recogido como basura por el recolector.
R: Existen al menos cuatro buenas maneras de asegurarse del cierre de un fichero:
(1) f = open "fichero" begin f.each {|l| print l} ensure f.close end (2) File.open("fichero") { |f| f.readlines.each{ |l| print l } } (3) IO.foreach("fichero" { |l| print l } (4) IO.readlines("fichero").each {|l| print l } |
R:
Dit.glob("*").sort{|a, b| File.mtime(b) <=> File.mtime(a) } |
Una forma mucho más eficiente se puede obtener añadiendo un poco de complejidad:
Dir.glob("*").collect {|f| [File.mtime(f),f]}. sort{|a, b| b{0} <=> a[0].collect!{|e| e[1]} |
R:
freq = Hash.new(0) open("example").read.scan(/\w+/){|w| freq[w] += 1 } freq.keys.sort.each {|k| print k, "-", freq[k], "\n"} |
and-1 is-3 line-3 one-1 this-3 three-1 two-1 |
R: ¡En Perl, una cadena vacía ("") devuelve false y Ruby true en una expresión condicional!
En Ruby, y dentro de contextos condicionales sólo es falso nil y false. Es una manera de obtener velocidad - tanto nil como false son valores inmediatos por lo que se pueden chequear sin tener que seguir la referencia al objeto.
Para comprobar si está vacía una cadena se puede utilizar empty?, o comparar directamente con "" o verificar si la longitud (length) es 0.
R: Si se desea ordenar cadenas como 'AAA', 'BBB', ... 'ZZZ', 'aaa', 'bbb', ... los operadores incluídos en el lengueje valdrán. Pero si se desea ordenar distinguiendo entre mayúsculas y ninúsculas, hay que comparar dentro del bloque de ordenación la versión en minúsculas:
array = %w(z bB Bb BB bb Aa aA AA aa a) puts array.sort{ |a, b| a.downcase <=> b.downcase } |
a aa AA aA Aa bb BB bB Bb z |
Si se desea ordenar de tal forma que las Aes mayúsculas y las aes munúsculas aparezcan juntas, pero se considera que a es mayor que A (es decir que 'Aa' aparece después de AA pero antes de AB), hay que utilizar:
puts array.sort { |a, b| (a.downcase <=>b.downcase).nonzero? || a <=> } |
a AA Aa aA aa BB Bb bB bb z |
R: Devuelve el código del caracter 'a', 97 (Fixnum). Se puede expresar el código de un caracter como entero anteponiendo al mismo una interrogación, luego ?a es también 97 (Fixnum).
R: Si a contiene la cadena a expandir, se podría utilizar uno de los siguientes códigos:
1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+' '+*(8-$1.size%8*$2.size)} |
1 while a.sub!(/\t(\t*)/){' '*(8-$ .begin(0)%8+8*$1.size)} |
a.gsub!(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")} |
R: Regex.quote('\\') representa a una barra invertida.
Es más problemático si se utiliza sub y gsub, digamos que se tiene gsub(/\\/,'\\\\') con lo que se espera reemplazar toda barra invertida por dos. Durante el análisis sintáctico el segundo parámetro pasa a ser '\\'. Cuando tiene lugar la sustitución, el motor de expresiones regulares lo pas a '\', luego el efecto que se obtiene es reemplazar toda barra invertida por otra. Hay que escribir gsub!(/\\/,'//////')!.
Pero, dado que \& contiene la cadena a buscar, se posría escribir gsub(/\\/,'/&/&').
Si se utilizan los bloques de gsub, p. e. gsub(/\\/){'\\\\'}, la cadena de sustitución sólo se analida una vez (surante la fase sintáctica) y el resultado es el deseado.
R: Con sub se genera una copia del receptor, se sustituye y se devuelve.
Con sub!, se modifica el receptor y se devuelve su se encuentra una coincidencia. Sino se devuelve nil.
Los métodos como sub! se conocen como métodos destructivos (ver la sección 7.13) es decir, modifican los atributos del receptor. Si existen dos métodos similares y uno de ellos es destructivo, el destructivo lleva como sufijo !.
def foo(str) str = str.sub(/foo/,"baz") end obj = "foo" foo(obj) # -> "baz" obj # -> "foo" def foo(str) str = str.sub!(/foo/,"baz") end foo(obj) # -> "baz" obj # -> "baz" |
R: \Z coincide con el carácter anterior a un \n si la cadena finaliza con él, sino con el final de la cadena.
R: Desde una variable se puede referenciar a un objeto Proc obtenido con Proc.new.proc o lambda, por lo que se puede considerar que esa variable es un puntero a una función. Se pueden obtener referencias a métodos dentro de una instancia concreta de un objeto utilizando Object.method.
R: Los threads en Ruby están implementados en el interprete, mientras que fork realiza una llamada al sistema operativo para crear un proceso en ejecución independiente.
Thread y fork tienen las siguientes características:
fork es lento, thread no.
fork no comparte el espacio de memoria.
thread no provoca trasiego.
thread funciona sobre DOS.
Cuando un thread se bloquea, todo el proceso se detiene.
fork puede aprovechar las paradas en espera de E/S, thread no (al menos sin algún tipo de ayuda).
Probablemente la mejor opción es una mezcla de fork y thread.
R: Marshal se utiliza para almacenar un objeto en un fichero o en una cadena y recuperarlo posteriormente. Los objetos se pueden almacenar utilizando:
Marshal.dump obj [, io][, lev] |
Si se omite io, los objetos aplanados se devuelven en una cadena.
Se pueden recuperar los objetos con
obj = Marshal.load io # o obj = Marshal.load str |
R: Ruby tiene un esquema flexible de manejo de excepciones:
begin sentencias que pueden generar una excepción rescue [nombres de clases de excepción] sentencias a ejecutar cuando ha ocurrido una excepción rescue [nombres de clases de excepción] sentencias a jecuy¡tar cuando ha ocurrido una excepción ensure sentencias que siempre se han de ejecutar. end |
Si en la clausula rescue no se indica ninguna clase de excepción, se supone que es StandardError y toda escepción descendiente de ésta es recogida.
Esta expresión devuelve el valor de la clausula begin.
Con $! se puede acceder a la última excepción generada (y su tipo se puede determinar con $!.type).