12

The law of non-contradiction dictates that two contradictory statements cannot both be true at the same time. That means that the expressions

(a && !a)
(a == !a)
(a === !a)

should always evaluate to a falsy value, and

(a || !a)

should always evaluate to a truthy value.

Fortunately, though, Javascript is a fun language that allows you to do all sorts of sick things. I bet someone a small fortune that it's possible to convince Javascript to break the law of non-contradiction, or, at least, convincingly make it look like it's breaking the law of non-contradiction. Now I'm trying to make all four of the above code examples give the unexpected result.

What would be a good way to go about this?

Community
  • 1
  • 1
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • 1
    @djhaskin That sound like a question a programmer who only likes merely practical programs would ask. – Peter Olson Aug 13 '11 at 21:20
  • You can just define a class in C++ and overload && to always return true. No? – Patrick87 Aug 13 '11 at 21:21
  • @Patrick, Yes, in C, but Javascript doesn't have operator overloading. – Peter Olson Aug 13 '11 at 21:22
  • Oh, so you mean JavaScript specifically. Gotcha. – Patrick87 Aug 13 '11 at 21:25
  • @Peter: `==` doesn't correspond to logical equality. `===` is closer. – outis Aug 13 '11 at 21:25
  • @outis Yes, I realize that. If somebody comes up with a solution that matches `===`, I will definitely be impressed at their JS-fu. – Peter Olson Aug 13 '11 at 21:28
  • 1
    Here's an interesting exercise in tri-value logic: `(!(((0/0) && !(0/0)) == false) && !(((0/0) && !(0/0)) == true)) === true`. In other words, `(0/0) && !(0/0)` is an `a` st `!(a==false) && !(a==true)`. Works just as well with `===`. Doesn't break logic the way you asked, but still... – outis Aug 13 '11 at 21:29
  • @Peter: since `==` isn't the same as logical equality, finding an `a` st `a == !a` doesn't break logic, though it may be a step towards breaking transitivity of `==`. – outis Aug 13 '11 at 21:32
  • As outis mention, using "==" will not break the law. Cause JavaScript is not type safe, it needs to convert values of different types to the same to compare them. So in the end you dont compare the same object but two objects that was created by converting your original object by JavaScript. – Andreas Köberle Aug 13 '11 at 21:42

4 Answers4

7

The best I can do is:

[] == ![] // true

or

var a = []; 
a == !a

Of course this is really doing [] == false // true and !![] == ![] // false. It's really just a technicality.

EDIT: This is really a joke, but does work:

var a = false; var b = function() { return a = !a };
console.log(!!(b() && !b())); // true
console.log(b() == !b()); // true
console.log(b() === !b()); // true
console.log(b() || !b()); // true
Joe
  • 80,724
  • 18
  • 127
  • 145
  • So `[] == false` but `!![] == true`. Thanks for sharing. – pimvdb Aug 13 '11 at 21:28
  • 1
    As long as you use "==" JavaScript tries to convert the values to the same type. So in your example ![] will be converted to false and then JavaScript converts the empty array to '', which is falsy values in JavaScript. – Andreas Köberle Aug 13 '11 at 21:36
4

This one will do the trick:

var a = '0';
a == !a

(evaluates to true)

In this case, a == false and !a == false.

mopsled
  • 8,445
  • 1
  • 38
  • 40
  • No it doesn't. You dont compare a with a, but a with !a. In JavaScript !a will convert to false, cause it's String and so, its a true value, which you convert to flase using !. Then you compare false with '0'. This will be converted to false by converting it first to a number which is 0, which is a falsy value in JavaScript. So in the end you compare false and false and not '0' to itself. – Andreas Köberle Aug 13 '11 at 21:51
  • @eskimoblood By the process you described, the javascript engine will use the `==` (equality) operator to compare `a` and `!a`, and find that the two are not equal. The dynamic type conversion **is the reason** that expressions like this one in javascript can seem to violate simple logic, and I think this is the sort of example @Peter was looking for. – mopsled Aug 13 '11 at 21:59
  • In my understanding it would only break if "==" would compare two objects by itself not the converted types. – Andreas Köberle Aug 13 '11 at 22:06
2

a=NaN;

var a=NaN, 
A=[(a && !a), (a == !a),(a === !a),(a || !a)];
alert(A)

/*  returned value: (Array)
NaN,false,false,true
*/
kennebec
  • 102,654
  • 32
  • 106
  • 127
1

I still haven't found anything to break && and ===, but here's one for == and ||:

Object.prototype.toString = function() {
    return false;
};
a = {};
b = (a || !a);
alert(a || !a);  //alerts false
alert(b == !b);  //alerts true
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • That doesn't really break `||`. `a || !a` results in `{}`, which is still a true value. Also, you're adding an axiom that equates true values with a false value. The resulting inconsistency is one you create, not one that exists in JS. – outis Aug 13 '11 at 21:55
  • @outis Yes, yes, I know. Actually breaking the law of non-contradiction, is, of course, impossible, so you have to be creative and just make it look like it does. – Peter Olson Aug 13 '11 at 22:21