3

Booleans are often used to model domain specific dichotomies. The most common example I can think of is the success or failure of an operation. It seems to me that a boolean must be interpreted in the context in which it is used as opposed to something more specific to the domain of the function. What is the advantage to returning a boolean from a function over returning something like a enumeration of named values?

Assume the programming language we are using succinctly deals with both booleans and enumerations so readability is not an issue.

  • 5
    Philosophers have debated for thousands of years: what is truth? – user22815 Mar 2 '15 at 20:46
  • 1
    Haskell typically goes with the domain-specific abstractions because it is so easy to do, both syntactically and semantically. – Thomas Eding Mar 3 '15 at 0:15
2

What is the advantage to returning a boolean from a function over returning something like a enumeration of named values?

It let's programmers be lazy. Sometimes that is a virtue. Things like this, it is not.

The main advantage is that at the call-site, using a bool is often more readable:

if(foo.IsBar){ ... }

Rather than:

if(foo.Bar == enum.Good){ ... }

The enum will be marginally more readable in Bar than IsBar, but that code is only in one spot. The property/function will be called in more spots, so we favor making that code more readable.

And then there's the fact that everything else already uses bools. If you need to take the result and pass it into existing code, the enum needs adapted to some truthy value, further hurting readability.

Again, this is in general. Usually booleans + good name can be made more readable. Sometimes enums will be more readable. Use the right one for the problem at hand.

| improve this answer | |
  • I feel like the answer to almost every question man has every asked can be described metaphorically as having different shades of gray. It's the train of thought that got me thinking about this question in the first place. I can think of very few answers that are truly black or white, so why is bool so useful? xD – mortalapeman Mar 2 '15 at 21:30
  • @mortalapeman Sadly computers only understand black or white, so you have to make the leap from fuzzy to binary somewhere. – grahamparks Mar 3 '15 at 9:42
3

A very large reason for this is probably support: many languages and libraries are designed to support booleans or generic, dichotomous values over more-specific variants so that they have the widest applicability.

For example: if supports booleans. If we wanted if to be able to support any dichotomy (ignoring equality comparisons on the values) then it'd probably have to be parameterized (if<OpReuslt,Success>(...)) or have to test using some sort of Dichotomy type class / interface which we'd have to implement for everything we wanted to be testable (in which case it'd still be using something common to everything, like a boolean). Both of these seem a PITA.

In Haskell, F#, etc, there is the algebraic data type Either (Choice in F#) for representing one of two possible values. There are many libraries which use these constructs to interface with the rest of a program. If each tried to use its own abstraction then they'd all have to support the abstractions of the others or you'd have to have some sort of conversion layer.

There's also the fact that boolean values are often used in some sort of algebraic computation and if something else were used they'd have to be converted to some common type before these computations could take place, so why not use booleans to begin with?

| improve this answer | |
  • I didn't know about Choice in F#, thank you for that. As usual with programming, the correct answer is "be pragmatic." – mortalapeman Mar 2 '15 at 21:39
2

Any data type can be thought of as able to hold the answer to a question. What is two plus two? The integer four. What is pi? The floating point with a certain bit pattern. Is the sky blue? A yes/no, true/false answer.

These are primitives, meaning data elements are reusable across a broad spectrum of uses and generally are simple, often fitting into a single CPU register. Does each function that calculates an integer need its own enum or custom data structure? No. Does each function that returns a yes/no response need the same? No.

Sometimes a function needs to return a discrete number of responses. If there are more than two responses, use an enum. If there are two valid responses and they are not yes/no or true/false, use an enum (e.g. red/green, weekend/weekday, billable/nonbillable). If the responses are true or false, use a boolean. That is why it exists.

| improve this answer | |
  • 2
    I agree that the point of bools in current programming is to quickly model a dichotomy by trading specificity for programmer's time. However, I feel that this is more due to legacy and pragmatism than bools being the most correct answer to the problem. – mortalapeman Mar 2 '15 at 21:20
  • 2
    @mortalapeman I disagree, sometimes true/false or yes/no really is the most correct way to represent something. Not all binary answers are, as I mentioned in my answer. But often it is. – user22815 Mar 2 '15 at 21:28
  • 1
    Mathematics is the only domain I can think of where answers are black or white. And to be pedantic, yes/no is a named enumeration ;) – mortalapeman Mar 2 '15 at 21:36
  • 1
    Did I eat chicken for dinner last night? Very black or white answer: there is no "maybe" and this is not a mathematical domain. – user22815 Mar 2 '15 at 23:17
  • 1
    Did the function return True for failure or True for success? I have no idea. But when a function returns Success for success and Failure for failure, the meaning is crystal clear. – Thomas Eding Mar 3 '15 at 6:08
1

Sometimes you just need to know whether an operation succeeded or not.

The most straightforward example that I can think of is the TryParse metaphor in the .NET Framework. TryParse exists for a number of reasons:

  1. You can control the lifetime of the variable you're putting the parse result into,
  2. Exceptions are too expensive to be throwing if you're in the middle of a long loop, and
  3. A success flag allows an appropriate value to be substituted for a failed parse (like zero, perhaps).

TryParse looks like this:

bool result SomeNumericType.TryParse(string text, out SomeNumericType value)

Let's say you're trying to parse some numeric columns in a large text file as quickly as possible, but one of the columns contains a text character. If you use a Parse method that throws exceptions, you've just crippled your parser.

On the other hand, if you do something like this:

public double ParseColumn(string text)
{
    double number= 0;
    if (double.TryParse(text), out number)
        return number;
    else
    {
        // optionally analyze text for the reasons why, log the problem, or whatever
        return 0;
    }
}

Then you've avoided having to trap the dreaded exception, an operation that is typically three orders of magnitude slower than returning an error code or success result, and you've lowered the overhead as much as humanly possible for the general case (a successful parse operation).

| improve this answer | |
  • I one hundred percent agree with TryParse over the regular Parse functions. I can't tell you how much code I have cleaned up due to over use of the non Try* variants. However, I was trying to ask my question from a language agnostic point of view where the semantics of how a bool vs enum was handled in code had no impact on readability or performance. – mortalapeman Mar 2 '15 at 21:27
  • [shrug] TryParse isn't language-specific, and if readability and performance aren't factors, I would imagine that it comes down to personal preference. – Robert Harvey Mar 2 '15 at 22:32
  • I think TryParse is not a good example. Instead, int.Parse should return an Option<int> etc. – Jörg W Mittag Mar 3 '15 at 11:33
  • @JörgWMittag: Is that a Maybe monad? – Robert Harvey Mar 3 '15 at 16:02
  • @RobertHarvey: I was thinking about some form of Option or Maybe type, yes. Which may or may not be a monad, depending on how it is implemented (although it makes sense to implement it as one, especially in languages and on platforms such as Haskell, Scala, VB.NET, C#, .NET which have specific syntactic (monad comprehensions, for comprehensions, query comprehensions) or library (Control.Monad, LINQ) support for them). – Jörg W Mittag Mar 3 '15 at 16:06
1

Because the domain answer is just another boolean. LetterSent, BillPaid, AccountIsPastDue, SubscribedToAutoPay, etc...

When you talk to the domain experts, that is how they think of the situation -- the main difference is that they typically think in terms of yes/no and not true/false, but creating an object for that would be silly -- basically a lot of extra work for a simple ToString method.

| improve this answer | |
  • But when foo.LetterSent is true, has it arrived, or is it still in transit? Has the postal office even seen it yet? Perhaps enum LetterStatus would be better, describing the location of the letter more accurately. – Ben Leggiero Feb 16 '18 at 20:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.