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?
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?
Respostas:
: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.
"foo".equal? "foo"
falso? b) Você pode se referir a um símbolo em qualquer lugar, essencialmente fazendo-o como variáveis globais?
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.
"foo" == "foo"
# => true
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.
==
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.
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
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".
Em ruby, cada objeto tem um identificador de objeto exclusivo; se você escrever puts "hello".object_id
em seu irb e pressionar return por 2 vezes diferentes, obterá 2 valores retornados diferentes, mas se escrever :hello.object_id
2 vezes, obterá apenas o mesmo valor retornado. Isso deveria ter explicado a diferença.
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.
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".
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 :symbol
será 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.
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.