Feture Request: Result should be truthy

This should work. Why make developer tack on extra code to get something that should've worked like the below? With this change, developers won't need to is_ok() and they can write code faster.

let n = Ok("test");
if n {
    println!("woah");
}

Rust prefers explicit type conversions, so it doesn't have truthiness for integers or anything else. But if you like, I made a sort of joke crate that will do what you want for Result:

https://crates.io/crates/eh

It's not really any better than is_ok, except that you can use it generically.

18 Likes

Because it's more obvious what the explicit code does.

Having to call methods explicitly is not a prime obstackle of writing code quickly. Programmers don't power-type pre-memorized snippets.

Anyway, languages shouldn't be optimized for writing quickly. They should be optimized for reading easily and maintaining/changing code with the smallest possible chance of introducing bugs. We spend much more time reading code than writing.

26 Likes

Note that right now Rust doesn't have any "truthiness" -- only bool can be used in if and while conditions. No containers; no pointers; no options; no integers. This is unlikely to change.

A big reason for that is that truthiness actually works poorly in a type-oriented language. Having it leads to code like

if n {
    println!("woah {}!", n.unwrap());
}

But that's not a good way to write it.

Rather than truthiness, that code wants pattern matching:

if let Ok(n) = n {
    println!("woah {}!", n);
}

See Boolean Blindness | Existential Type for a good explanation of how bool is often an anti-pattern, since it doesn't mean anything on its own -- you have to look of where it came from to understand it.

(As a simple example of that, both .is_ok() and .is_err() return true. So you clearly don't know anything just from having a true. If you want a very long article explaining the consequences of following through on this idea, see Aiming for correctness with types .)

39 Likes

Beside the general objection to implicit boolness, there is one more problem here. A pretty big one.

Is Ok the truish value, or is it Err?

That's actually unambiguous, because of the existing methods like Result::and and Result::or. Their semantics only match the normal definition of and if Ok is "true" and Err is "false".

15 Likes

You might still ask about the value within Ok -- the truthy crate chose to look for inner truthiness too. Though as you say, that doesn't fully align with Result's own and/or.

6 Likes

OK, but consider BufRead::has_data_left

if reader.has_data_left() {
    println!("Yes");
} else {
    println!("No");
}

If there is data left to read, it'd print "Yes". If there is no data left to read, it'd also print "Yes". Only if there was an IO error when checking the reader it would print "No".

3 Likes

Sure, inner truthiness makes sense in that scenario. It's still not consistent with Result::and/or, but sometimes it may be what you want. The truthy crate also gives you truthy_and/or methods, so I guess they tried to answer that difference.

You can also pattern-match that particular case:

if let Ok(true) = reader.has_data_left() { ... }
1 Like

I think that's another excellent of why not to have truthiness. I can immediately think of three different things that I might want that to do, and I'm glad that Rust makes me pick.

30 Likes