Hacker News new | ask | show | jobs
by dwrensha 3630 days ago
I recommend Bob Harper's essay on "boolean blindness": https://existentialtype.wordpress.com/2011/03/15/boolean-bli...

An excerpt:

> The problem is computing the bit in the first place. Having done so, you have blinded yourself by reducing the information you have at hand to a bit, and then trying to recover that information later by remembering the provenance of that bit.

2 comments

Thats why you use Lua, it lets you have multiple return values. So you can get a boolean back to let you know if the strings were the same, an int to know where they ceased matching and a boolean to let you know if they are case different. It's then up to the programmer to decide how much enlightenment they want.

The destroy all IF reminds me of GOTO considered harmful of the 70's. There are other ways to fix the problem.

Multiple return values are a great idea IMO, and I learned to really appreciate them in Common Lisp. They're best used as additional bits of information that the programmer may or may not find useful. Like that string comparison example of yours. Or #'gethash[0], that will return the value from hash table you're looking for or a default value (which is optional and by default NIL) if there is no entry with a given key, but it'll also return a second, boolean value that tells you whether your return value was actually found or not - which cleanly solves the problem of storing NILs in hash tables, in the places you care about it.

Multiple return values feel elegant also because the compiler can optimize them away when you're not using them, which is the most common case.

[0] - http://clhs.lisp.se/Body/f_gethas.htm

That still has the problem of boolean blindness. The boolean you get back doesn't tell you what it means, you have to go looking for that information.
What's the difference between multiple return values and returning a tuple?

(Apart from that languages with multiple return values tend to have some special syntax for binding only the first few members of the returned tuple?)

Apart from what you mention, it's often not possible to pass along all of the multiple return values as a single value.
The difference, in terms of type theory, is that a tuple is a product type [1] but a type representing multiple possible return values (to represent different outcomes) would be encoded using a sum type [2].

[1] https://en.wikipedia.org/wiki/Product_type

[2] https://en.wikipedia.org/wiki/Tagged_union

I don't think eg Go uses a sum type:

https://gobyexample.com/multiple-return-values

Typically they use product types to simulate sum types.

The Lua solution is clutter. Why return a boolean just to switch on it and then discard it?
Why create a lambda just to execute it and then discard it?
The problem with the Boolean is rather that people mix up the two values all the time.

The lambda also has more type safety. A Boolean is always a Boolean, but the compiler (and in a dynamic language the runtime) can tell you when you are calling your passed functions with the wrong arguments, because you mixed them up.

Use an enum.
No need to stop there. Not only use an enum, but also make it bear different types of values for different cases, and you arrive at Algebraic Datatypes. Eg, for trees you can have:

    data Tree = Empty
              | Leaf Int
              | Node Tree Tree
Can't that argument be extended to, say, uint8_t, and from there to all sorts of computed values?