2009-02-25 9 views

risposta

12

In primo luogo, non penso che i cortocircuiti possano applicarsi sensibilmente a XOR: qualunque sia il valore del primo operando, il secondo deve essere esaminato.

In secondo luogo e, & &, oppure e || usare cortocircuiti in tutti i casi; l'unica differenza tra le versioni "word" e "symbol" è la precedenza. Credo che and e or sono presenti per fornire la stessa funzione di perl ha in linee come

process_without_error or die 

Penso che il motivo per non avere una xor funzione denominata probabilmente è che non ha senso in un operatore di bassa priorità in questo caso e che è già una situazione abbastanza confusa!

+0

Penso che "nessun punto in precedenza bassa' funzione xor' "non sia corretto. In Perl ero usato per controllare due parametri CGI esclusivi con qualcosa come 'param1 xor param2'. Peccato, ho bisogno di farlo in un modo più complicato in Ruby. – geronime

+1

Al giorno d'oggi, sono d'accordo sul fatto che 'and' e' or' siano il flusso di controllo. Avdi ha scritto bene su http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ (infatti, ho collegato a questa domanda nella sezione commenti di quella post del blog) –

17

No, non lo è, è possibile utilizzare solo ^.

Non so perché non è particolarmente, potrebbe essere solo perché non è così comunemente usato.

+1

'^' corre in problemi con valori truthy. Ho definito la mia funzione: – John

+0

Sono appena stato colpito da questo. Sto usando ruby-prof per migliorare un algoritmo e ho pensato che semplificare alcune condizioni con uno XOR avrebbe reso più veloce. Ma è il contrario. – Papipo

+0

Siamo spiacenti di non accettare, ma preferisco la risposta di Mike al giorno d'oggi. –

10

Prova ^

true^false #=> true 
true^true #=> false 
false^false #=> false 

No pianura operatore equivalente inglese però.

14

mi sono imbattuto in un problema perché l'operatore '^' agisce bit a bit sui numeri,

true^1 
=> false 

1^true 
TypeError: can't convert true into Integer 
true^1 

così la mia soluzione era:

(!!a^!!b) dove il doppio-bang li costringe in booleani.

!!1^!!true 
=> false 

!!1^!!false 
=> true 
+1

Interessante, ma non molto pertinente alla domanda. – Macha

+1

++ Utile. Sono venuto qui a cercare XOR, ma so come fare il contrario, cioè costringere un bool a_i? Il mio altro operando è già un int, e ho bisogno che il risultato sia int. – Marcos

+0

@Macha + 1ing perché ho appena riscontrato lo stesso problema e non ci sono altre domande sugli xors booleani di Ruby che non riguardavano le stringhe. –

1

Qualsiasi implementazione di xor non consentirà cortocircuiti. Entrambe le espressioni devono essere valutate a prescindere da cosa.

Ruby fornisce l'operatore ^, ma questo soffocherà sui valori di verità. Ho implementato una funzione per gestire i casi in cui voglio un xor che si comporta più come and e or:

def xor(a,b) 
    (a and (not b)) or ((not a) and b) 
end 

differenza ^, questa funzione può essere utilizzata in situazioni di simile al seguente:

xor("hello".match(/llo/), false) # => true 
xor(nil, 1239)     # => true 
xor("cupcake", false)   # => false 
+1

Risposta/commento di Chris Phoenix su 'xor (" cupcake ", false)' restituire true è corretto. –

2

La risposta di John non è corretta. In irb con 1.9.3, xor ("cupcake", false) restituisce true, come ci si aspetterebbe.

1.9.3-p429 :104 > def xor(a,b) 
1.9.3-p429 :105?>  (a and (not b)) or ((not a) and b) 
1.9.3-p429 :106?> end 
=> nil 
1.9.3-p429 :107 > xor(false, true) 
=> true 
1.9.3-p429 :108 > xor("cupcake", false) 
=> true 
6

In alternativa al doppio trucco negazione di Matt Van Horn per l'utilizzo di XOR sui tipi arbitrari, è possibile concatenare un altro test XOR, a partire da nil. cioè:

!!foo^!!bar 

è equivalente a

nil^foo^bar 

Questo sembra più ordinato al mio occhio, e suppongo che richiede un'operazione meno logico

+0

Soluzione piacevole –