22

Sometimes I have a function that should return true or false. But sometimes three possible values would make more sense.

In some language theses cases would be handled with integers or with exceptions.

For exemple you want to handle the age of a user if he is over 18 years old. And you have a function like this.

if(user.isAdult(country_code)){
     //Go On
}else{
     // Block access or do nothing
}

But in some case depending how your app is built I could see case where the birthday field is incomplete. Then this function should return something undetermined.

switch(user.isAdult()){
    case true:
        // go on
        break;
    case undetermined:
        //Inform user birthday is incomplete
    case false:
        //Block access
}

As I said we can handle that with Exceptions and Int, but I would find it quite sexy to have a true, false, undetermined embeded in the language instead of using some home defined constants.

11
  • 15
    Obligatory TDWTF link: thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx :)
    – Adam Lear
    Dec 30, 2010 at 14:47
  • 2
    @Anna Lear: Damn, you beat me to it. ^^
    – gablin
    Dec 30, 2010 at 14:53
  • 3
    gablin: Damn, you even beat me to complaining about Anna.
    – user281377
    Dec 30, 2010 at 15:20
  • 1
    Ugh, I wanted to get the T,F,FNF too! shakes fist
    – Mike M.
    Dec 30, 2010 at 15:23
  • 4
    @gablin, @ammoQ, @Mike M.: Sorry. :)
    – Adam Lear
    Dec 30, 2010 at 15:40

12 Answers 12

35

This can be handled with either enums, integers, symbols (e.g., Lisp, Ruby), nullable types (use null as the indeterminate state), option types (e.g., ML), or some similar construct - depending on your language.

So while your example and rationale is sound I can't see it being on the priority list of language features to develop.

7
  • null in C/C++ is supposed to equal false. In these cases you'd have to return -1. I think undetermined state is quite frequent but is always treated differently because this syntax doesn't really exist. In java a boolean function cannot return anything else than true or false for a boolean function. So you are forced to use a different type and document well the returned value. Dec 30, 2010 at 14:58
  • @Sybiam - there's nothing wrong with using a different type where appropriate. As I said I can see an argument for a trinary type, but I can't see it being added to existing languages any time soon.
    – ChrisF
    Dec 30, 2010 at 15:02
  • 6
    @Sybiam: In Java you can return a Boolean, which can be null. In C/C++ you can return an enum.
    – Macneil
    Dec 30, 2010 at 15:20
  • this is madness! Dec 30, 2010 at 16:38
  • 2
    @Macneil maybe Sparta?
    – syockit
    Apr 25, 2011 at 12:26
6

true, false, unknown

yes, no, maybe

in C# you can use a nullable bool (you may recoil in horror now)

in MS-SQL, you can use a nullable bit field (ditto)

4
  • 2
    The problem with nullable booleans isn't that they have nulls, so much as most people (me included) don't know anything about three-valued logic. Which one, for starters: scientopia.org/blogs/goodmath/2010/08/24/… Dec 30, 2010 at 15:30
  • True/False/None. Dec 30, 2010 at 15:46
  • 2
    Funny thing is, a lot of people understand binary, octal, and hex, but can't wrap their minds around ternary. Why is that? same thing, just base three...that would solve the three value logic problem.
    – Michael K
    Dec 30, 2010 at 18:34
  • 5
    Most people just have a fear of the unknown.
    – dan04
    Jan 9, 2011 at 16:54
5

I have not seen a case where this is necessary. In the example you've given, if that field is necessary it should have been validated elsewhere. isAdult() is inherantly a two-state method: You either are or you aren't. There is no need to have it do anything but return false if it encounters data it can't handle. For instance:

switch(user.isAdult()){
   case true:
      // go on
      break;
   default:
      // Block access.
}
3
  • 2
    If data is invalid it can ask user to fix it which is different than being underage where you don't ask the person to input a new age. This is 2 different behaviours. For exemple some social sites lets you input incomplete birthdays for privacy. Dec 30, 2010 at 14:56
  • 2
    I think that validation should be performed in another area/section of code. Validate the data first, and then operate on it.
    – Michael K
    Dec 30, 2010 at 15:01
  • 1
    @Sybiam: In general, applications don't ask for data on a haphazard basis, when they need it. You could have .isAdult() query the user itself, if that's really what you want, and that would work better. Dec 30, 2010 at 15:02
2

In C++, this can be handled with a non-bool return type, or by throwing an exception. If you want a three-valued return type, use an enum. It isn't as sexy, but it works, and what's more important you can do it without messing up the language for the rest of us.

Having bool be three-valued would cause problems. How do you handle bool foo; ... if (foo)..., assuming foo might have any of the three values? There's advantages to having bool variables such that precisely one of foo and !foo is true at all times. It helps reason about programs.

Check out what people do in numerical processing when they might possibly get NaN values. It's complicated. I'd rather not have to go through with it for ordinary boolean processing.

If you want .isAdult() to handle insufficient information, have it do that internally, and then return either true or false. Otherwise, every time you use it you need to check the return code before doing anything else, and come up with a way to handle it. It would mean you had to check the docs to see if a function actually did what its name said it did, and that would be a disaster for readability.

2

The idea is quite useful. There's a whole field devoted to dealing with uncertainty called Fuzzy Logic.

Fortunately for us programmers, you can implement fuzzy logic with standard language features.

For instance, in the case you gave, the uncertain information is easily determinable by asking the user. So a tri-state enum like you describe will work fine.

There are all kinds of other ways to be uncertain. Such questions include:

  • Will it rain tomorrow? It hasn't happened yet, so nobody can know - but you can make an educated guess and give a probability.
  • Is there multicellular life on a planet in the solar system of the star Beta Pictoris? It has a definite yes-or-no answer, but we can't currently tell what that is.

A lot of those questions can be dealt with using probabilities in the range 0.0 (false) to 1.0 (true), and applying floating point math.

A computational chemist and computer scientist named David E. Shaw applied this kind of thing to Wall Street and is now worth about $2.5 billion. So yes, it's useful. :-)

1

Many years ago I played with some of the algorithms that were coming out for assigning a belief to values. Was kind of fun. Ultimately what I gained from it is that boolean is often a contrived fit. Really it should be a trilean true/false/other value. In experimentation that seemed to lead to the "best" code for me at the time. I've since caved and do what everyone else does, while thinking internally how much simpler it COULD be if we'd quit doing things the same old way... :-)

0

Case or Switch statements would work fine for this, though, by using integers to arbitrarily deal with the switch.

Also, in Ruby, while 'nil' returns as false under some circumstances, if you use the equality operator, nil == false returns false, so you could use ruby nil to handle ternary logic.

0

Another option in your case might be to invert the control by applying the "tell don't ask" principal and change it to (sorry about the word adultness, brain blockage):

user.isAdult(new OnlyAllowAdultsToLogin())

where OnlyAllowAdultsToLoginStrategy implements an interface:

interface UserAdultnessPolicy
{
   void userIsAdult();
   void userIsChild();
   void userAdultnessIsUnknown();
}
1
  • What does void userIsAdult() do? Perhaps you meant bool userIsAdult()?
    – Timwi
    Dec 30, 2010 at 19:19
0

My son was asking me how to efficiently implement tests that resemble this. The flags being tested were only true/false, but the matchkeys had three states (It must be true, it must be false, or I don't care). Of course this can be implemented with a 2bit data structure and a bit of bit twiddling, but that sort of code really needs to be commented as the purpose isn't easy to discern from just looking at the code.

0

C has this feature implemented in most of the library functions. eg strcmp compares 2 strings and returns 0 if they are the same, 1 (ie any positive integer) if the 1st one is 'greater' than the 2nd, and -1 (ie any negative integer) if the second is greater than the first.

The same approach can be used elsewhere, +/0/- as your tri-state. It also lets you perform boolean logic on the values if you know 0 if false and any other value is true.

0

For C++, Boost actually implements a Tribool described as such :

The tribool class acts like the built-in bool type, but for 3-state boolean logic. The three states are true, false, and indeterminate, where the first two states are equivalent to those of the C++ bool type and the last state represents an unknown boolean value (that may be true or false, we don't know).

-1

The VB6 checkbox has this capability. The checkbox values can be 0=off, 1=on, 2=grayed

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