Um aquecimento:
>> nil && true
=> nil
>> nil || true
=> true
>> !(nil && true)
=> true
>> !nil || !true
=> true
Vamos aumentar um pouco:
>> !!(nil && true)
=> false
>> !(!nil || !true)
=> false
>> !(!nil && !true)
=> true
Dar um tempo. Certifique-se de que você colocou sua cabeça em volta do último. Pronto? Vamos explodir algumas mentes:
>> !nil || !true === false
=> true
>> !nil || !true === !false
=> true
Agora, satori:
>> nil === false
=> false
>> nil === true
=> false
>> nil && true === false
=> nil
>> nil && true === true
=> nil
O que está acontecendo nesses quatro conjuntos de exemplos? As Leis de De Morgan definem o comportamento dos principais operadores booleanos! (não), && (e) e || (ou). “Nem ambos” é logicamente equivalente a “Nem um nem outro”, e “ambos” é logicamente equivalente a “nem um nem outro”. Esses são os pilares da álgebra booleana.
No entanto, os lógicos e algumas linguagens de programação como Ruby podem fazer mais com lógicas adicionais. No último conjunto, não pense em nil, true e false como valores booleanos típicos. Pense neles como quantificadores sobre os elementos de um conjunto: nil significa nenhum elemento em um conjunto, verdadeiro significa alguns elementos em um conjunto e falso significa (possivelmente) um outro conjunto de elementos, complementar a algum conjunto.
A comparação de nil com verdadeiro ou falso perguntará se aqueles elementos abrangidos pelo conjunto vazio (ou seja, nenhum) são os mesmos elementos no conjunto comparado. Eles não são.
E os dois exemplos finais? Não tenho certeza se isso está correto, mas gosto de pensar que a intersecção do conjunto vazio e algum conjunto é um conjunto vazio diferente do contido em outro, inclusivo ou exclusivo. Mas essa é uma interpretação metafísica limítrofe, e me pergunto se há uma avaliação mais lógica ou computacionalmente precisa.
(Esclarecimento: Rubistas experientes irão – corretamente – questionar esta última declaração. Só para ficar claro, é uma declaração sobre lógica, não sobre Ruby. Em Ruby, a comparação suave verificará se dois objetos têm a mesma ‘veracidade’, que quer dizer, o mesmo valor funcional de verdade conforme definido pela linguagem de programação. A comparação estrita verificará se dois objetos são, de fato, o mesmo objeto Ruby.)
Veja: http://mathworld.wolfram.com/deMorgansLaws.html
Nota: Esta postagem foi escrita com um bebê atacando o teclado.
Revisão principal: 02/05/2013