¿Cuál es el operador de colon en Ruby?
symbol (9)
Cuando digo { :bla => 1, :bloop => 2 }
, ¿qué hace exactamente el :
do? Leí en alguna parte acerca de cómo es similar a una cuerda, pero de alguna manera un símbolo.
No tengo muy claro el concepto, ¿podría alguien iluminarme?
En ruby, cada objeto tiene un identificador de objeto único, si escribe puts "hello".object_id
en su irb y pulsa retorno por 2 veces diferentes, obtendrá 2 valores de retorno diferentes, pero si escribe :hello.object_id
2 veces Solo obtén el mismo valor de retorno. Eso debería haber explicado la diferencia.
Es un simbolo Básicamente, estás diciendo que los dos elementos del hash tienen claves bla
y bloop
, como si hubieras usado las cadenas "bla"
y "bloop"
. Sin embargo, ocupan menos memoria que las cadenas y son más fáciles de escribir.
Hay algunas citas del famoso libro Agile Web Development with Rails , que pueden ser útiles para entender el símbolo también:
Los rieles usan símbolos para identificar cosas. En particular, los utiliza como claves al nombrar parámetros de método y buscar elementos en hashes.
redirect_to :action => "edit", :id => params[:id]
Puedes pensar en los símbolos como literales de cuerdas que se convierten mágicamente en constantes. Alternativamente, puedes considerar que los dos puntos significan "la cosa llamada", entonces: id es "la cosa llamada identificación".
Los símbolos son una forma de representar cadenas y nombres en ruby.
La principal diferencia entre los símbolos y las cadenas es que los símbolos del mismo nombre se inicializan y existen en la memoria solo una vez durante una sesión de ruby.
Son útiles cuando necesitas usar la misma palabra para representar diferentes cosas.
Si está familiarizado con Java, es posible que sepa que las cadenas en Java son inmutables. Los símbolos son similares en ese sentido en Ruby. Son inmutables, es decir, cualquier número de apariciones de un símbolo particular :symbol
asignará a una sola dirección de memoria. Y, por lo tanto, se recomienda usar símbolos siempre que sea posible, ya que optimiza el uso de la memoria.
Si usa :foo => bar
, foo será un símbolo. El beneficio de los símbolos es que son únicos. Cuando llamas a un elemento del hash, haces hash[:foo]
.
Los símbolos requieren menos memoria que las cadenas, lo que también los hace útiles si desea que su programa sea un poco más rápido.
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
Ejecutándolo salidas:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
Entonces, ¿comparar una cadena con una cadena usando equal?
falla porque son objetos diferentes, incluso si son contenido igual. ==
compara el contenido, y las verificaciones 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 las mismas en cuanto a velocidad. Después de 1,000,000 iteraciones hay solo 0,004733 de diferencia, así que diría que es un lavado entre el cual usar.
Todas estas respuestas omiten un detalle tentador adicional ... si encadena el símbolo: foo, obtienes ... adivina qué ... la cadena "foo". Por lo tanto
irb(main):025:0>
irb(main):026:0> :foo
=> :foo
irb(main):027:0> "#{:foo}"
=> "foo"
irb(main):028:0>
irb(main):029:0> ''foo'' <=> :foo
=> nil
irb(main):030:0> ''foo'' <=> :foo.to_s
=> 0
irb(main):031:0>
Por lo tanto ... para los programadores de Perl ... es la respuesta de Ruby a la "palabra simple".
:foo
es un símbolo llamado "foo". Los símbolos tienen la característica distintiva de que dos símbolos con el mismo nombre serán idénticos:
"foo".equal? "foo" # false
:foo.equal? :foo # true
Esto hace que la comparación de dos símbolos sea realmente rápida (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á un millón de copias del mismo símbolo flotando alrededor.
Además, a diferencia de las cadenas, los símbolos son inmutables.