¿Qué es el operador de colon en Ruby?


Cuando digo { :bla => 1, :bloop => 2 }, ¿qué hace exactamente el :? Leí en alguna parte sobre cómo es similar a una cadena, pero de alguna manera un símbolo.

No tengo muy claro el concepto, ¿podría alguien iluminarme?

 199
Author: the Tin Man, 2011-06-14

9 answers

:foo es un símbolo llamado "foo". Los símbolos tienen la característica distinta de que dos símbolos con el mismo nombre serán idénticos:

"foo".equal? "foo"  # false
:foo.equal? :foo    # true

Esto hace que comparar dos símbolos sea muy 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 de que no tendrá un millón de copias del mismo símbolo flotando.

También, a diferencia de las cadenas, los símbolos son inmutables.

 227
Author: Chris Jester-Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-14 00:33:20

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

Ejecutarlo produce:

"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 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 las mismas en cuanto a velocidad. Después de 1,000,000 iteraciones, solo hay 0.004733 segundos de diferencia, así que diría que es un lavado entre los cuales utilizar.

 41
Author: the Tin Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-23 17:28:21

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 solo existen en la memoria una vez durante una sesión de ruby.

Son útiles cuando necesitas usar la misma palabra para representar cosas diferentes

 29
Author: nunopolonia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-14 00:34:21

Hay algunas citas del famoso libro Agile Web Development with Rails , que también pueden ser útiles para entender el símbolo :

Rails utiliza símbolos para identificar cosas. En particular, los usa como claves al nombrar parámetros de métodos y buscar cosas en hashes.

redirect_to :action => "edit", :id => params[:id]

Puedes pensar en símbolos como literales de cadena que se convierten mágicamente en constantes. Alternativamente, puede considerar que el colon significa " la cosa named", so :id es "la cosa llamada id".

 15
Author: Scott YAN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-23 08:45:46

En ruby cada objeto tiene un identificador de objeto único, si escribes puts "hello".object_id en tu irb y presionas return 2 veces diferentes, obtendrás 2 valores de retorno diferentes,pero si escribes :hello.object_id 2 veces solo obtendrás el mismo valor de retorno. Eso debería haber explicado la diferencia.

 4
Author: Devin Huang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-24 12:58:22

Si usas :foo => bar, foo será un símbolo. El beneficio de los símbolos es que son únicos. Cuando se llama a un elemento en el hash, se hace hash[:foo].

Los símbolos requieren menos memoria que las cadenas, lo que también los hace útiles si desea hacer que su programa sea un poco más rápido.

 2
Author: Charles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-23 21:36:17

Es un símbolo. 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.

 0
Author: kindall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-14 00:34:50

Todas estas respuestas omiten un detalle adicional tentador.. si usted stringify el símbolo: foo, usted consigue.. adivina qué.. la cuerda "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 programadores de Perl.. es la respuesta de Ruby a la "palabra desnuda".

 0
Author: Frank Carnovale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-23 13:43:37

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 ocurrencias de un símbolo en particular :symbol se asignará a una sola dirección de memoria. Y, por lo tanto, se recomienda utilizar símbolos siempre que sea posible, ya que optimiza el uso de la memoria.

 -1
Author: Dhruva Sagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-23 17:20:24