Qual é o operador de dois pontos no Ruby?

234

Quando digo { :bla => 1, :bloop => 2 }, o que exatamente faz :? Eu li em algum lugar sobre como é semelhante a uma corda, mas de alguma forma um símbolo.

Não sou muito claro sobre o conceito, alguém poderia me esclarecer?

LuxuryMode
fonte
1
possível duplicata de símbolos Entendendo Em Ruby
Mladen Jablanović
7
Tente olhar para isto: O Guia Ruby_Newbie de Símbolos
Hengjie
Este vídeo mostra tudo o que você precisa saber sobre símbolos.
totymedli

Respostas:

249

:fooé um símbolo chamado "foo". Os símbolos têm o recurso distinto de que quaisquer dois símbolos com o mesmo nome sejam idênticos:

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

Isso torna a comparação de dois símbolos muito rápida (já que apenas uma comparação de ponteiro está envolvida, em vez de comparar todos os caracteres como você faria em uma string), além de não haver um zilhão de cópias do mesmo símbolo flutuando.

Além disso, diferentemente das strings, os símbolos são imutáveis.

Chris Jester-Young
fonte
2
pergunto-me por que a string literal não suporta internamento de strings?
precisa saber é o seguinte
5
@ onmyway133 Porque as seqüências de Ruby são mutáveis. A internação se aplica apenas a valores imutáveis.
Chris Jester-Young
3
a) Por que é "foo".equal? "foo"falso? b) Você pode se referir a um símbolo em qualquer lugar, essencialmente fazendo-o como variáveis ​​globais?
Arc676
2
@ Arc676 1. equal?em Ruby faz comparação de identidade. Cada literal de string, como "foo", cria uma nova instância de string. Funciona assim porque as strings no Ruby são mutáveis. 2. Os símbolos são globais, mas mais como constantes globais do que variáveis ​​globais, pois os símbolos não têm estado. Portanto, o uso de símbolos não é um antipadrão da maneira que as variáveis ​​globais são.
Chris Jester-Young
2
@ Arc676 "foo" == "foo"# => true
Filip Bartuzi #
44

Apenas para demonstrar algumas das coisas mencionadas nas respostas:

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

Em execução, ele produz:

"foo".equal? "foo" -> false
"foo" == "foo"     -> true
:foo.equal? :foo   -> true
:foo == :foo       -> true

Portanto, comparar uma string com uma string usando equal?falha porque são objetos diferentes, mesmo que tenham conteúdo igual. ==compara o conteúdo e as verificações equivalentes com símbolos são muito mais 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)

Ambos os testes de símbolos são basicamente os mesmos em relação à velocidade. Após 1.000.000 de iterações, há apenas 0,004733 segundos de diferença, então eu diria que é uma lavagem entre as quais usar.

o homem de lata
fonte
Extremamente útil! No meu sistema, ==resultou mais rápido do que .equal?nas comparações de cadeias e símbolos. A comparação de símbolos resultou três vezes mais rápido que as comparações de strings.
precisa saber é o seguinte
33

Os símbolos são uma maneira de representar seqüências de caracteres e nomes em ruby.

A principal diferença entre símbolos e seqüências de caracteres é que símbolos com o mesmo nome são inicializados e existem na memória apenas uma vez durante uma sessão de ruby.

Eles são úteis quando você precisa usar a mesma palavra para representar coisas diferentes

nunopolonia
fonte
19

Existem algumas citações do famoso livro Agile Web Development with Rails , que também podem ajudar a entender o símbolo :

O Rails usa símbolos para identificar as coisas. Em particular, ele os utiliza como chaves ao nomear parâmetros de métodos e procurar coisas em hashes.

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

Você pode pensar em símbolos como literais de seqüência de caracteres que são magicamente transformados em constantes. Como alternativa, você pode considerar os dois pontos como "a coisa chamada", portanto: id é "a coisa chamada id".

shyan1
fonte
5

Em ruby, cada objeto tem um identificador de objeto exclusivo; se você escrever puts "hello".object_idem seu irb e pressionar return por 2 vezes diferentes, obterá 2 valores retornados diferentes, mas se escrever :hello.object_id2 vezes, obterá apenas o mesmo valor retornado. Isso deveria ter explicado a diferença.

Devin Huang
fonte
Basicamente, o operador de cólon é para uma Atribuir símbolo
Cesar Jr Rodriguez
2

Se você usar :foo => bar, foo será um símbolo. O benefício para os símbolos é que eles são únicos. Quando você chama um item no hash, você o faz hash[:foo].

Os símbolos requerem menos memória que as strings, o que também as torna úteis se você deseja tornar seu programa um pouco mais rápido.

Charles
fonte
0

É um símbolo. Basicamente, você está dizendo que os dois elementos do hash têm chaves blae bloop, como se você tivesse usado as strings "bla"e "bloop". No entanto, eles ocupam menos memória que as seqüências de caracteres e são mais fáceis de digitar.

kindall
fonte
0

Todas essas respostas omitem um detalhe tentador extra .. se você especificar o símbolo: foo, terá .. adivinhem ... a string "foo". Conseqüentemente

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>

Portanto ... para programadores Perl ... é a resposta de Ruby para a "palavra nua".

Frank Carnovale
fonte
-1

Se você está familiarizado com Java, pode estar ciente de que Strings em Java são imutáveis. Os símbolos são semelhantes nesse sentido em Ruby. Eles são imutáveis, ou seja, qualquer número de ocorrências de um símbolo específico :symbolserá mapeado para apenas um único endereço de memória. Portanto, é recomendável usar símbolos sempre que possível, pois otimiza o uso da memória.

Dhruva Sagar
fonte
1
O fato de os símbolos serem imutáveis ​​garante que eles sempre sejam a mesma instância em todo o aplicativo e, portanto, eles garantem o mesmo objeto. Verifique estas referências: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/… Você encontrará muito mais se pesquisar no Google.
Dhruva Sagar
Estou falando da sua analogia com o Java. Java Strings não são análogas aos símbolos. Literais de strings Java são, mas não são todos, strings.
precisa saber é o seguinte
Talvez minha afirmação não tenha sido clara o suficiente. Eles são análogos entre si apenas no que diz respeito ao fato de serem imutáveis.
Dhruva Sagar
@DhruvaSagar: A analogia seria melhor se você usou de Objective-C NSString. Não "foo"vai ser sempre igual "foo", porque internamente cordas que são os mesmos estão apenas apontado. A resposta ainda seria confusa, no entanto.
Rafael Bugajewski