Log in


What is truth?

So here's a bit of a geeky post, but not so terribly geeky that I'm hiding the bulk behind a cut link.

"true" and "false" are simple concepts, right? Different programming languages seem to have hugely different ideas of what they are:

In C, 0 is false, any other integer is true, and the coercion rules make a null pointer false, and any other pointer true. Anything else is a compile error.

C++ follows (inherits?) the C rule, and adds true and false as things that are true and false.

In shell, 0 is a true exit value; any other exit value is false. Inside [ ], empty strings are false and other strings (such as "0" or "1") are true.

In Python, 0, 0.0, -0.0, False, None, the empty string, empty tuples, lists, and dicts are all false. Anything else (such as the string '0') is true. (A note on 0.0 vs -0.0: they're both == according to python, and both false, but print differently. One can be turned into the other by multiplying by -1)

In Perl, 0, the empty string, and undef are false, and since evaluation as a boolean imposes scalar context, an empty array or hash variable is also false. Anything else (including arrayref or hashref values to empty structures) is true. Note that because perl helpfully autoconverts like a $SOME_NOUN_HERE, the string "0" and 0.0 are to perl identical to 0, and therefore false. (hence the Perl idiom "0 but true") A full discussion of the quirks of perl around various representations of zero could probably fill a small book, but I'll note that other consequences are that the expression -0 is true, but -0.0 is false.

In Ruby, false and nil are false, anything else (including 0, the empty string, and an empty Array or Hash) is true.

In Javascript, 0, null, undefined, the empty string, false and NaN are false. Anything else (such as an empty Array, or empty Object) is true.

In Java, (since the autoboxing introduced in Java 1.5) true and Boolean.TRUE are true, false and Boolean.FALSE are false, ((Boolean) null) is a runtime exception, and anything else is a compile error.

In Haskell, True is true, False is false, and anything else is a compile error.

Google Go behaves like Java 1.4 or Haskell - true is true, false is false and anything else is a compile error.

Scala appears to behave the same way - true is true and false is false. Anything else (including an instance of RichBoolean, or of java.lang.Boolean) is a compile error.

In Common Lisp, nil, aka the empty list, is false. Anything else - including 0, the empty string or empty vectors of other types - is true.


C# requires a bool in branching constructs, so "true" is true and "false" is false and everything else is a red squiggly.

This is the Right Way to do it, I think. But I can live with Python's way, too. The real problem with the Python philosophy is that arguably float values shouldn't have a "false" because you shouldn't compare float values for direct equality, not even to 0.0.
So you're saying C# is like Haskell, Go, Scala or Java before 1.5 introduced implicit unboxing of Booleans.

What about a method that takes a ref bool parameter, and uses that parameter in a branching construct - can I pass a null pointer into that method? (without doing some reflection magic)

Will that compile? If so, where will it blow up at runtime?

I do agree that if you're going to make a floating point number be false, the only sensible one to do that with is NaN. (Okay, technically there are many NaN values, so my grammar's off in that sentence)
In C#, you can't assign something that could be null to a ref bool because bool is a value type and therefore not nullable.

C# has a syntax which allows you to specify that a variable might be a value type or null: bool? test = null. You can't use a bool? in a bool context without casting, though, and it will throw at runtime if you try to do the cast on something that is null.
I agree with you on NaN, but of course that could weirdness like 0 is false but (float) 0 is true. It's a wart, plain and simple. And we haven't even talked about +0.0 and -0.0, which exist in the IEEE spec even though people feel free to ignore them.
Python actually has -0.0 as the possible result of certain computations, and perl does odd things with the expression -0.0. Added them to the post.

(And other languages allow for -0.0 too, but it doesn't affect the true/false rules)

I don't know that I've ever seen a numerical engine that explicitly allowed for +0.0.
Also, I'd argue that there could be two Right Ways to do it, depending on whether you can have compile-time errors or not.

June 2016

Powered by LiveJournal.com