Complementando, tem alguns detalhes que mudam conforme a linguagem.
Por exemplo, em Java e C#, os operadores lógicos só aceitam operandos booleanos. Já em outras linguagens, como Python, PHP e JavaScript, eles aceitam operandos de qualquer tipo.
Isso porque em Python, PHP e JavaScript existe o conceito de valores truthy e falsy, ou seja, qualquer valor pode ser convertido para true
ou false
se estiver em um contexto booleano.
Então valores como a string vazia, null
/None
e o número zero geralmente são considerados false
, enquanto os demais valores são considerados true
. Essas regras são definidas por cada linguagem e podem haver variações, como por exemplo a string "0"
, que em PHP é considerado false
, enquanto que em Python e JavaScript é considerado true
(nessas, somente o número zero é false
, mas a string "0"
não, porque não é vazia). Ou a lista vazia, que em Python é "falsa", mas em JavaScript um array vazio é considerado "verdadeiro".
Ou seja, algo como por exemplo if (a && b)
é válido em JavaScript, independente do valor das variáveis a
e b
, mas em Java só seria válido se o tipo dessas variáveis fosse boolean
.
Outro detalhe importante é que nem sempre o resultado do operador é um boolean
. Em Python e JavaScript, por exemplo, o retorno sempre é um dos operandos. Exemplo:
a = 'abc'
b = 42
c = a and b
print(c)
d = a or b
print(d)
No caso do and
, se o primeiro operando for verdadeiro (seja booleano, ou qualquer valor que seja correspondente a True
), o resultado é o valor do segundo operando (caso contrário, retorna o valor do primeiro). E o or
retorna o primeiro operando se este for verdadeiro, senão retorna o segundo.
Então quando fazemos if a and b:
em Python, a expressão a and b
retorna um dos valores de a
ou b
, e em seguida este é convertido para boolean
para verificar se ele corresponde a "verdadeiro" ou "falso". Mas como podemos ver no exemplo acima, é possível usar o valor retornado diretamente, sem que este necessariamente faça parte de uma condição.
Por isso que é comum termos, por exemplo, coisas assim em JavaScript:
var x = valor1 || valor2 || valor3;
Ou seja, x
recebe o primeiro dos valores que não for equivalente a false
, ou o último, caso todos os anteriores sejam (lembrando que valores como o número zero, string vazia, null
e undefined
são considerados "falsos"). No caso, o código acima seria equivalente a:
var x;
if (valor1) {
x = valor1;
} else if (valor2) {
x = valor2;
} else {
x = valor3;
}
Já em outras linguagens (como Java, C# e PHP), o retorno destes operadores sempre é um boolean
(ou seja, apenas true
ou false
).
E uma curiosidade: PHP tem tanto os operadores and
/or
quanto &&
/||
. A diferença entre eles é a precedência.
Vale lembrar também que esses operadores costumam ser short-circuit, ou seja, só avaliam o mínimo necessário. Por exemplo, a && b
só é verdadeiro se ambos os operandos também o forem. Então se o primeiro é falso, ele nem avalia o segundo. Já a || b
só é falso se ambos também o forem, então se o primeiro for verdadeiro, ele nem avalia o segundo.
Exemplo em JavaScript:
function a() {
console.log('chamando a()');
return false;
}
function b() {
console.log('chamando b()');
return true;
}
console.log('testando &&');
console.log(a() && b());
console.log('\ntestando ||');
console.log(b() || a());
A saída é:
testando &&
chamando a()
false
testando ||
chamando b()
true
Por fim, o XOR do JavaScript é apenas um operador bitwise, ou seja, ele trabalha com operandos numéricos e faz o XOR bit a bit dos seus valores. Por exemplo, se tivermos 14 ^ 9
, o resultado é 7
:
14 (00001110)
9 (00001001)
----------------
7 (00000111) <-- XOR bit a bit
É claro que se os números forem iguais (como 2 ^ 2
) o resultado será 0
, que equivale a false
. Mas se os valores não forem números, como por exemplo 'a' ^ ''
, o resultado também é zero (se o operador fosse lógico, o resultado deveria ser equivalente a true
, já que a string 'a'
é considerada verdadeira, enquanto a string vazia é falsa).
No caso, para simular o XOR lógico em JavaScript, teria que fazer algo como if (Boolean(a) !== Boolean(b))
(ou if (!a !== !b)
, já que o uso do operador !
força a coerção para booleano).