Qual è l'operatore di due punti in Ruby?


234

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?



7
Prova a guardare questo: The Ruby_Newbie Guide to Symbols
Hengjie

Questo video ti dice tutto ciò che devi sapere sui simboli.
totymedli,

Risposte:


249

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


2
chiedo solo perché la stringa letterale non supporta l'internazionalizzazione delle stringhe?
onmyway133,

5
@ onmyway133 Perché le stringhe di Ruby sono mutabili. Il interning si applica solo a valori immutabili.
Chris Jester-Young,

3
a) Perché è "foo".equal? "foo"falso? b) Puoi riferirti a un simbolo ovunque, essenzialmente rendendolo come variabili globali?
Arc676,

2
@ Arc676 1. 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.
Chris Jester-Young,

2
@ Arc676 "foo" == "foo"# => true
Filip Bartuzi,

44

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.


Estremamente utile! Sul mio sistema, è ==risultato più veloce rispetto .equal?ai confronti di stringhe e simboli. Il confronto dei simboli è risultato 3 volte più veloce dei confronti delle stringhe.
melvynkim,

33

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


19

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".


5

In ruby ​​ogni oggetto ha un identificatore univoco dell'oggetto, se scrivi puts "hello".object_idnel tuo irb e premi Invio per 2 volte diverse, otterrai 2 valori di ritorno diversi, ma se scrivi :hello.object_id2 volte otterrai solo lo stesso valore di ritorno. Questo avrebbe dovuto spiegare la differenza.


Fondamentalmente l'operatore del colon deve assegnare un simbolo
Cesar Jr Rodriguez,

2

Se lo usi :foo => bar, foo sarà un simbolo. Il vantaggio dei simboli è che sono unici. Quando chiami un elemento nell'hash, lo fai hash[:foo].

I simboli richiedono meno memoria delle stringhe, il che li rende utili anche se vuoi rendere il tuo programma un po 'più veloce.


0

È un simbolo Fondamentalmente, stai dicendo che i due elementi dell'hash hanno le chiavi blae bloop, proprio come se avessi usato le stringhe "bla"e "bloop". Tuttavia, occupano meno memoria delle stringhe e sono più facili da digitare.


0

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".


-1

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 :symbolverrà mappato su un solo indirizzo di memoria. E, quindi, si consiglia di utilizzare i simboli ove possibile poiché ottimizza l'utilizzo della memoria.


1
Il fatto che i simboli siano immutabili garantisce che siano sempre la stessa istanza in tutta l'applicazione e quindi siano garantiti per essere lo stesso oggetto. Controlla questi riferimenti: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/… Troverai molto di più se vai su Google.
Dhruva Sagar,

Sto parlando della tua analogia con Java. Le stringhe Java non sono analoghe ai simboli. I letterali delle stringhe Java sono ma non tutte le stringhe.
smartnut007,

Forse la mia affermazione non era abbastanza chiara. Sono analoghi tra loro solo rispetto al fatto che sono immutabili.
Dhruva Sagar,

@DhruvaSagar: L'analogia sarebbe meglio se si è utilizzato di Objective C NSString. Ci "foo"sarà sempre uguale "foo", perché le stringhe interne uguali sono solo indicate. La risposta sarebbe comunque confusa.
Rafael Bugajewski,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.