Quando dico { :bla => 1, :bloop => 2 }
, cosa fa esattamente :
? Ho letto da qualche parte come è simile a una stringa, ma in qualche modo un simbolo.
Non sono molto chiaro sul concetto, qualcuno potrebbe illuminarmi?
Quando dico { :bla => 1, :bloop => 2 }
, cosa fa esattamente :
? Ho letto da qualche parte come è simile a una stringa, ma in qualche modo un simbolo.
Non sono molto chiaro sul concetto, qualcuno potrebbe illuminarmi?
Risposte:
:foo
è un simbolo chiamato "pippo". I simboli hanno la caratteristica distintiva che due simboli uguali identici saranno identici:
"foo".equal? "foo" # false
:foo.equal? :foo # true
Questo rende il confronto tra due simboli molto veloce (dal momento che è coinvolto solo un confronto puntatore, invece di confrontare tutti i caratteri come faresti in una stringa), inoltre non avrai a disposizione milioni di copie dello stesso simbolo che fluttua.
Inoltre, a differenza delle stringhe, i simboli sono immutabili.
"foo".equal? "foo"
falso? b) Puoi riferirti a un simbolo ovunque, essenzialmente rendendolo come variabili globali?
equal?
in Ruby fa il confronto delle identità. Ogni stringa letterale, come "foo"
, crea una nuova istanza di stringa. Funziona in questo modo perché le stringhe in Ruby sono modificabili. 2. I simboli sono globali, ma più simili alle costanti globali che alle variabili globali, poiché i simboli non hanno stato. Quindi l'uso dei simboli non è un antipattern nel modo in cui lo sono le variabili globali.
"foo" == "foo"
# => true
Giusto per dimostrare alcune delle cose menzionate nelle risposte:
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
Eseguendolo emette:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
Quindi, il confronto tra una stringa e una stringa usando equal?
non riesce perché sono oggetti diversi, anche se hanno lo stesso contenuto. ==
confronta il contenuto e i controlli equivalenti con i simboli sono molto più veloci.
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)
Entrambi i test dei simboli sono sostanzialmente gli stessi per quanto riguarda la velocità. Dopo 1.000.000 di iterazioni c'è solo una differenza di 0,004733 secondi, quindi direi che è un lavaggio tra cui usare.
==
risultato più veloce rispetto .equal?
ai confronti di stringhe e simboli. Il confronto dei simboli è risultato 3 volte più veloce dei confronti delle stringhe.
I simboli sono un modo per rappresentare stringhe e nomi in rubino.
La principale differenza tra simboli e stringhe è che i simboli con lo stesso nome sono inizializzati ed esistono in memoria solo una volta durante una sessione di ruby.
Sono utili quando devi usare la stessa parola per rappresentare cose diverse
Ci sono alcune citazioni dal famoso libro Agile Web Development with Rails , che possono essere utili anche per comprendere il simbolo :
Rails utilizza simboli per identificare le cose. In particolare, li usa come chiavi per nominare i parametri del metodo e cercare cose negli hash.
redirect_to :action => "edit", :id => params[:id]
Puoi pensare ai simboli come letterali stringa che sono magicamente trasformati in costanti. In alternativa, puoi considerare i due punti come "la cosa chiamata", quindi: id è "la cosa chiamata id".
In ruby ogni oggetto ha un identificatore univoco dell'oggetto, se scrivi puts "hello".object_id
nel tuo irb e premi Invio per 2 volte diverse, otterrai 2 valori di ritorno diversi, ma se scrivi :hello.object_id
2 volte otterrai solo lo stesso valore di ritorno. Questo avrebbe dovuto spiegare la differenza.
Tutte queste risposte omettono un dettaglio in più allettante ... se stringi il simbolo: pippo, ottieni .. indovina un po '.. la stringa "pippo". Quindi
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>
Quindi ... per i programmatori Perl ... è la risposta di Ruby alla "parola nuda".
Se hai familiarità con Java, potresti essere consapevole che le stringhe in Java sono immutabili. I simboli sono simili in tal senso in Ruby. Sono immutabili, ovvero qualsiasi numero di occorrenze di un particolare simbolo :symbol
verrà mappato su un solo indirizzo di memoria. E, quindi, si consiglia di utilizzare i simboli ove possibile poiché ottimizza l'utilizzo della memoria.
NSString
. Ci "foo"
sarà sempre uguale "foo"
, perché le stringhe interne uguali sono solo indicate. La risposta sarebbe comunque confusa.