¿Cuál es el operador de colon en Ruby?

234

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

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

LuxuryMode
fuente
1
posible duplicado de símbolos
Mladen Jablanović
77
Trate de ver esto: La Guía Ruby_Newbie de Símbolos
Hengjie
Este video le dice todo lo que necesita saber sobre los símbolos.
totymedli

Respuestas:

249

:fooes 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.

Además, a diferencia de las cadenas, los símbolos son inmutables.

Chris Jester-Young
fuente
2
solo me pregunto por qué la cadena literal no admite el internamiento de cadenas
onmyway133
55
@ onmyway133 Porque las cuerdas de Ruby son mutables. La internación solo se aplica a valores inmutables.
Chris Jester-Young
3
a) ¿Por qué es "foo".equal? "foo"falso? b) ¿Puedes referirte a un símbolo en cualquier lugar, esencialmente haciéndolos como variables globales?
Arc676
2
@ Arc676 1. equal?en Ruby hace una comparación de identidad. Cada literal de cadena, como "foo", crea una nueva instancia de cadena. Funciona de esa manera porque las cadenas en Ruby son mutables. 2. Los símbolos son globales, pero se parecen más a las constantes globales que a las variables globales, ya que los símbolos no tienen estado. Por lo tanto, usar símbolos no es un antipatrón en la forma en que lo son las variables globales.
Chris Jester-Young
2
@ Arc676 "foo" == "foo"# => verdadero
Filip Bartuzi
44

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 de iteraciones, solo hay una diferencia de 0.004733 segundos, por lo que diría que es un lavado entre el cual usar.

el hombre de hojalata
fuente
¡Extramadamente útil! En mi sistema, ==resultó más rápido que .equal?para las comparaciones de cadenas y símbolos. La comparación de símbolos resultó 3 veces más rápida que las comparaciones de cadenas.
melvynkim
33

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

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

nunopolonia
fuente
19

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

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

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

Puede pensar en los símbolos como literales de cadena que se convierten mágicamente en constantes. Alternativamente, puede considerar que los dos puntos significan "la cosa llamada", entonces: id es "la cosa llamada id".

shyan1
fuente
5

En ruby, cada objeto tiene un identificador de objeto único, si escribe puts "hello".object_iden su irb y presiona return por 2 veces diferentes, obtendrá 2 valores de retorno diferentes, pero si escribe :hello.object_id2 veces solo obtendrá el mismo valor de retorno. Eso debería haber explicado la diferencia.

Devin Huang
fuente
Básicamente, el operador de colon es para asignar un símbolo
Cesar Jr Rodriguez
2

Si lo usas :foo => bar, foo será un símbolo. El beneficio de los símbolos es que son únicos. Cuando llamas a un elemento en el hash, lo 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.

Charles
fuente
0

Es un símbolo Básicamente, estás diciendo que los dos elementos del hash tienen claves blay bloop, como si hubieras utilizado las cadenas "bla"y "bloop". Sin embargo, ocupan menos memoria que las cadenas y son más fáciles de escribir.

un poco
fuente
0

Todas estas respuestas omiten un detalle extra tentador ... si cadenas 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 desnuda".

Frank Carnovale
fuente
-1

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 particular se :symbolasignará 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.

Dhruva Sagar
fuente
1
El hecho de que los símbolos sean inmutables garantiza que siempre sean la misma instancia en toda la aplicación y, por lo tanto, se garantiza que sean el mismo objeto. Verifique estas referencias: troublehooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/… Encontrará muchas más si busca en Google.
Dhruva Sagar
Estoy hablando de tu analogía con Java. Las cadenas de Java no son análogas a los símbolos. Los literales de cadena de Java son pero no todas las cadenas.
smartnut007
Quizás mi declaración no fue lo suficientemente clara. Son análogos entre sí solo con respecto al hecho de que son inmutables.
Dhruva Sagar
@DhruvaSagar: La analogía sería mejor si se ha utilizado de Objective C NSString. No "foo"siempre va a ser igual "foo", porque internamente cadenas que son el mismo se acaba de señalar a. Sin embargo, la respuesta aún sería confusa.
Rafael Bugajewski