Operatori di uguaglianza: == e! =
L'operatore ==, noto anche come uguaglianza o doppio uguale, restituirà vero se entrambi gli oggetti sono uguali e falso in caso contrario.
"koan" == "koan" # Output: => true
L'operatore! =, Noto anche come disuguaglianza, è l'opposto di ==. Restituirà vero se entrambi gli oggetti non sono uguali e falso se sono uguali.
"koan" != "discursive thought" # Output: => true
Si noti che due matrici con gli stessi elementi in un ordine diverso non sono uguali, le versioni maiuscole e minuscole della stessa lettera non sono uguali e così via.
Quando si confrontano numeri di tipi diversi (ad esempio, intero e float), se il loro valore numerico è lo stesso, == restituirà true.
2 == 2.0 # Output: => true
pari?
A differenza dell'operatore == che verifica se entrambi gli operandi sono uguali, il metodo uguale controlla se i due operandi si riferiscono allo stesso oggetto. Questa è la forma più rigorosa di uguaglianza in Ruby.
Esempio: a = "zen" b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
Nell'esempio sopra, abbiamo due stringhe con lo stesso valore. Tuttavia, sono due oggetti distinti, con ID oggetto diversi. Quindi, uguale? il metodo restituirà false.
Riproviamo, solo che questa volta b sarà un riferimento a. Si noti che l'ID oggetto è lo stesso per entrambe le variabili, poiché puntano allo stesso oggetto.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
EQL?
Nella classe Hash, l'eql? metodo viene utilizzato per testare le chiavi per l'uguaglianza. Sono necessari alcuni retroscena per spiegare questo. Nel contesto generale dell'informatica, una funzione hash accetta una stringa (o un file) di qualsiasi dimensione e genera una stringa o un numero intero di dimensioni fisse chiamato hashcode, comunemente noto come solo hash. Alcuni tipi di hashcode comunemente usati sono MD5, SHA-1 e CRC. Vengono utilizzati negli algoritmi di crittografia, nell'indicizzazione del database, nel controllo dell'integrità dei file, ecc. Alcuni linguaggi di programmazione, come Ruby, forniscono un tipo di raccolta chiamato tabella hash. Le tabelle hash sono raccolte simili a dizionari che memorizzano i dati in coppie, costituiti da chiavi univoche e dai relativi valori. Sotto il cofano, quei tasti sono memorizzati come hashcode. Le tabelle hash sono comunemente chiamate solo hash. Notare come la parola hashcan si riferisce a un hashcode o a una tabella hash.
Ruby fornisce un metodo integrato chiamato hash per la generazione di hashcode. Nell'esempio seguente, prende una stringa e restituisce un hashcode. Notare come le stringhe con lo stesso valore abbiano sempre lo stesso hashcode, anche se sono oggetti distinti (con ID oggetto diversi).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
Il metodo hash è implementato nel modulo Kernel, incluso nella classe Object, che è la radice predefinita di tutti gli oggetti Ruby. Alcune classi come Symbol e Integer utilizzano l'implementazione predefinita, altre come String e Hash forniscono le proprie implementazioni.
Symbol.instance_method(:hash).owner # Output: => Kernel
Integer.instance_method(:hash).owner # Output: => Kernel
String.instance_method(:hash).owner # Output: => String
Hash.instance_method(:hash).owner # Output: => Hash
In Ruby, quando memorizziamo qualcosa in un hash (collezione), l'oggetto fornito come chiave (ad es. Stringa o simbolo) viene convertito e memorizzato come hashcode. Successivamente, quando recuperiamo un elemento dall'hash (raccolta), forniamo un oggetto come chiave, che viene convertito in un codice hash e confrontato con le chiavi esistenti. Se esiste una corrispondenza, viene restituito il valore dell'articolo corrispondente. Il confronto viene effettuato utilizzando l'eql? metodo sotto il cofano.
"zen".eql? "zen" # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true
Nella maggior parte dei casi, l'eql? Il metodo si comporta in modo simile al metodo ==. Comunque, ci sono alcune eccezioni. Ad esempio, eql? non esegue la conversione di tipo implicita quando si confronta un numero intero con un float.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Operatore di uguaglianza dei casi: ===
Molte delle classi incorporate di Ruby, come String, Range e Regexp, forniscono le proprie implementazioni dell'operatore ===, noto anche come case-uguaglianza, tripli uguali o trequali. Poiché è implementato in modo diverso in ogni classe, si comporterà in modo diverso a seconda del tipo di oggetto su cui è stato chiamato. In genere, restituisce true se l'oggetto a destra "appartiene a" o "è un membro di" l'oggetto a sinistra. Ad esempio, può essere utilizzato per verificare se un oggetto è un'istanza di una classe (o una delle sue sottoclassi).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Lo stesso risultato può essere ottenuto con altri metodi che sono probabilmente più adatti per il lavoro. Di solito è meglio scrivere codice che sia facile da leggere essendo il più esplicito possibile, senza sacrificare l'efficienza e la concisione.
2.is_a? Integer # Output: => true
2.kind_of? Integer # Output: => true
2.instance_of? Integer # Output: => false
Si noti che l'ultimo esempio ha restituito false perché numeri interi come 2 sono istanze della classe Fixnum, che è una sottoclasse della classe Integer. Il ===, is_a? e istanza_di? i metodi restituiscono true se l'oggetto è un'istanza della classe specificata o delle sottoclassi. Il metodo instance_of è più rigoroso e restituisce true solo se l'oggetto è un'istanza di quella classe esatta, non una sottoclasse.
L'is_a? e tipo_di? i metodi sono implementati nel modulo Kernel, che è mischiato dalla classe Object. Entrambi sono alias dello stesso metodo. Verifichiamo:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Output: => true
Intervallo di implementazione di ===
Quando l'operatore === viene chiamato su un oggetto intervallo, restituisce vero se il valore a destra rientra nell'intervallo a sinistra.
(1..4) === 3 # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6 # Output: => false
("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false
Ricordare che l'operatore === invoca il metodo === dell'oggetto a sinistra. Quindi (1..4) === 3 equivale a (1..4). === 3. In altre parole, la classe dell'operando di sinistra definirà quale implementazione del metodo === sarà chiamato, quindi le posizioni degli operandi non sono intercambiabili.
Regexp Implementazione di ===
Restituisce vero se la stringa a destra corrisponde all'espressione regolare a sinistra. / zen / === "pratica zazen oggi" # Output: => true # è uguale a "pratica zazen oggi" = ~ / zen /
Uso implicito dell'operatore === sulle istruzioni case / when
Questo operatore viene utilizzato anche sotto il cofano delle istruzioni case / when. Questo è il suo uso più comune.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
Nell'esempio sopra, se Ruby avesse implicitamente usato il doppio operatore uguale (==), l'intervallo 10..20 non sarebbe considerato uguale a un numero intero come 15. Corrispondono perché l'operatore triplo uguale (===) è usato implicitamente in tutte le istruzioni case / when. Il codice nell'esempio sopra è equivalente a:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Operatori di corrispondenza dei motivi: = ~ e! ~
Gli operatori = ~ (equal-tilde) e! ~ (Bang-tilde) vengono utilizzati per abbinare stringhe e simboli a schemi regex.
L'implementazione del metodo = ~ nelle classi String e Symbol prevede un'espressione regolare (un'istanza della classe Regexp) come argomento.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
L'implementazione nella classe Regexp prevede una stringa o un simbolo come argomento.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
In tutte le implementazioni, quando la stringa o il simbolo corrispondono al modello Regexp, restituisce un numero intero che rappresenta la posizione (indice) della corrispondenza. Se non c'è corrispondenza, restituisce zero. Ricorda che, in Ruby, qualsiasi valore intero è "verità" e zero è "falsa", quindi l'operatore = ~ può essere usato in istruzioni if e operatori ternari.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Gli operatori di corrispondenza dei modelli sono utili anche per scrivere istruzioni if più brevi. Esempio:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
L'operatore! ~ È l'opposto di = ~, restituisce vero quando non c'è corrispondenza e falso se c'è una corrispondenza.
Maggiori informazioni sono disponibili in questo post del blog .
"a" == "a"
,"a" === "a"
e"a".eql? "a"
. Ma questo è falso:"a".equal? "a"
(il mio è rubino 1.9.2-p180)