¿Qué es el operador de dos puntos en Ruby?
Cuando digo { :bla => 1, :bloop => 2 }
, ¿qué hace exactamente :
? Leí en alguna parte que es similar a una cadena, pero de alguna manera es un símbolo.
No tengo muy claro el concepto, ¿alguien podría iluminarme?
:foo
es un símbolo llamado "foo". Los símbolos tienen la característica distintiva de que dos símbolos cualesquiera con el mismo nombre serán idénticos:
"foo".equal? "foo" # false
:foo.equal? :foo # true
Esto hace que comparar dos símbolos sea realmente rápido (ya que solo se trata de una comparación de puntero, en lugar de comparar todos los caracteres como lo haría en una cadena), además no tendrá millones de copias del mismo símbolo flotando.
Además, a diferencia de las cadenas, los símbolos son inmutables.
Solo para demostrar algunas de las cosas mencionadas en las respuestas:
require 'benchmark'
n = 1_000_000
print '"foo".equal? "foo" -> ', ("foo".equal? "foo"), "\n"
print '"foo" == "foo" -> ', ("foo" == "foo" ), "\n"
print ':foo.equal? :foo -> ', (:foo.equal? :foo ), "\n"
print ':foo == :foo -> ', (:foo == :foo ), "\n"
Benchmark.bm(10) do |b|
b.report('string') { n.times { "foo".equal? "foo" }}
b.report('str == str') { n.times { "foo" == "foo" }}
b.report('symbol') { n.times { :foo.equal? :foo }}
b.report('sym == sym') { n.times { :foo == :foo }}
end
Al ejecutarlo se obtiene:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
Entonces, comparar una cadena con otra usando equal?
falla porque son objetos diferentes, incluso si tienen el mismo contenido. ==
compara el contenido y las comprobaciones equivalentes con símbolos son mucho más rápidas.
user system total real
string 0.370000 0.000000 0.370000 ( 0.371700)
str == str 0.330000 0.000000 0.330000 ( 0.326368)
symbol 0.170000 0.000000 0.170000 ( 0.174641)
sym == sym 0.180000 0.000000 0.180000 ( 0.179374)
Ambas pruebas de símbolos son básicamente iguales en cuanto a velocidad. Después de 1.000.000 de iteraciones, solo hay una diferencia de 0,004733 segundos, por lo que diría que es un lavado entre los cuales usar.
Los símbolos son una forma de representar cadenas y nombres en Ruby.
La principal diferencia entre símbolos y cadenas es que los símbolos del mismo nombre se inicializan y existen en la memoria sólo una vez durante una sesión de Ruby.
Son útiles cuando necesitas usar la misma palabra para representar cosas diferentes.