2009-02-25 8 views

Respuesta

12

En primer lugar, no creo que el cortocircuito pueda aplicarse sensiblemente a XOR: sea cual sea el valor del primer operando, el segundo debe examinarse.

En segundo lugar, y, & &, oy || usar el cortocircuito en todos los casos; la única diferencia entre las versiones de "palabra" y "símbolo" es la precedencia. Creo que and y or están presentes para proporcionar la misma función que Perl tiene en líneas como

process_without_error or die 

Creo que la razón para no tener una función llamada xor es, probablemente, que no tiene sentido en un operador de bajo precedencia, en este caso y que ya es una situación bastante confusa!

+0

Creo que "no hay punto en la baja prioridad' función xor' "no es correcto. En Perl, usé para verificar dos parámetros exclusivos de CGI con algo como 'param1 xor param2'. Es una pena que necesite hacer esto de una manera más complicada en Ruby. – geronime

+1

Hoy en día, estoy de acuerdo con 'y' y' o' siendo el flujo de control. Avdi ha escrito bien sobre esto en http://devblog.avdi.org/2010/08/02/using-and-and-or-r-ruby/ (de hecho, he vinculado esta pregunta en la sección de comentarios de ese publicación de blog) –

17

No, no se puede, solo se puede usar ^.

No sé por qué no es particular, puede ser porque no es tan comúnmente utilizado.

+1

'^' se encuentra con problemas con valores Truthy. Definí mi propia función: – John

+0

Acabo de ser golpeado por esto. Estoy usando ruby-prof para mejorar un algoritmo, y pensé que simplificar alguna condición con un XOR lo haría más rápido. Pero es al revés. – Papipo

+0

Perdón por no aceptar, pero prefiero la respuesta de Mike hoy en día. –

10

Trate ^

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

Ningún operador equivalente Inglés llanura sin embargo.

14

me encontré con un problema porque el operador '^' actúa a nivel de bits en números,

true^1 
=> false 

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

así que mi solución era:

(!!a^!!b) el que el doble-bang les coacciona booleanos.

!!1^!!true 
=> false 

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

Interesante, pero no muy relevante para la pregunta. – Macha

+1

++ Útil. Vine aquí en busca de XOR, pero sé cómo hacer lo contrario, es decir, forzar un bool to_i? Mi otro operando ya es un int, y necesito que el resultado sea int. – Marcos

+0

@Macha + 1ing porque me acabo de encontrar con el mismo problema, y ​​no hay otras preguntas sobre Ruby boolean xors que no sean sobre cadenas. –

1

Cualquier implementación de xor no permitirá que un cortocircuito. Ambas expresiones deben ser evaluadas sin importar qué.

Ruby proporciona el operador ^, pero esto ahogará a los valores de verdad. He implementado una función para manejar los casos en el que necesito un xor que se comporta más como and y or:

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

A diferencia ^, esta función se puede utilizar en situaciones similares a lo siguiente:

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

Chris Phoenix responde/comenta acerca de 'xor (" cupcake ", false)' devolver verdadero es correcto. –

2

La respuesta de Juan parece incorrecta. En irb con 1.9.3, xor ("cupcake", false) devuelve true, como era de esperar.

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

Como alternativa a la doble negación truco de Matt Van Horn para usar XOR sobre los tipos arbitrarios, se pueden encadenar otra prueba XOR, a partir de nil. es decir:

!!foo^!!bar 

es equivalente a

nil^foo^bar 

Esto se ve más ordenado a mi ojo, y supongo que requiere una operación menos lógico

+0

Bonita solución –