# 4.6 Boolean values > Rust's bool type: true, false, the ! operator, and why there's no truthiness. Source: https://learnrust.net/chapter-4/boolean-values/ Do you like asparagus? Whatever your answer, it has a shape: yes or no, with no third option and no fraction. Programs are full of values shaped like that (is the file open, did the guess match, has the player lost), and Rust gives the shape a type: **bool**, with exactly two values, the literals `true` and `false`. ```rust fn main() { let lights_on = true; let door_locked = false; println!("{lights_on} {door_locked}"); } ``` ``` true false ``` Note that printing a bool prints the *word*, which sounds unremarkable until you learn that C++ prints `1` and `0` unless you ask nicely. A bool occupies one byte (lesson [4.1](@/chapter-4/introduction-to-fundamental-data-types.md)'s `size_of` told you so), making it Rust's smallest type, and the one your programs will consult most often. Bools have a dedicated operator: `!`, logical NOT, which flips the value. `!true` is `false`, and `!lights_on` is "the opposite of whatever `lights_on` is." (Its colleagues AND and OR arrive in lesson 6.5.) ## Where bools actually come from You'll type the literals occasionally, but most bools are *born from questions*. The comparison operators ask the questions: `==` (equal?), `!=` (not equal?), `<`, `>`, `<=`, `>=`. Each produces a bool: ```rust fn main() { let score = 87; let passed = score >= 60; let perfect = score == 100; println!("passed: {passed}"); println!("perfect: {perfect}"); println!("not perfect: {}", !perfect); } ``` ``` passed: true perfect: false not perfect: true ``` (87 clears the bar and misses perfection, a result many of us can confirm from experience.) (Chapter 6 gives the comparison operators their full lesson; this chapter uses them gently, mostly so the next lesson has questions to ask.) Functions that answer yes/no questions return bool, and the convention is to name them like questions: `is_empty`, `has_won`, `is_equal`. You can write one already with chapter 2 skills: ```rust fn is_even(n: i32) -> bool { n % 2 == 0 } fn main() { println!("{}", is_even(10)); println!("{}", is_even(7)); } ``` ``` true false ``` (`%` gives the remainder after division, as seen in lesson [2.4](@/chapter-2/local-scope-and-blocks.md); a number is even exactly when dividing by 2 leaves nothing.) The tail expression is a comparison, the comparison is a bool, and the bool is the return value: no `if` required, a small elegance worth imitating. ## There is no truthiness In many languages, non-bool values get drafted into yes/no service: C++ treats any non-zero number as "true," Python extends the idea to empty strings and lists, and every such language has a chapter of folklore about the surprises ("why is `"0"` truthy but `0` falsy?"). The term of art is *truthiness*, and Rust has none: ```rust fn main() { let count = 1; if count { println!("got some"); } } ``` ``` error[E0308]: mismatched types --> src/main.rs:3:8 | 3 | if count { | ^^^^^ expected `bool`, found integer ``` (A one-lesson preview of `if`, fully introduced next lesson.) An integer is not a bool, not even 0 or 1, and no value of any other type is secretly "true." Where a C++ programmer writes `if (count)`, hoping readers know it means "non-zero," a Rust programmer writes what they mean: `if count != 0`, or `if count > 0`, which aren't the same question, and the language just made you notice that. {% callout(kind="note", title="Key insight") %} "No truthiness" is the same design reflex you saw with [implicit conversions](@/chapter-4/integer-types.md): where a convenience blurs meaning, Rust deletes the convenience and keeps the meaning. The two keystrokes you save with `if (count)` are repaid in code where every condition states its actual question. {% end %} ## Quiz time **Question #1** What does this print? ```rust fn main() { let a = 5; let b = 10; println!("{}", a < b); println!("{}", !(a < b)); println!("{}", a != 5); } ```
Show solution ``` true false false ``` 5 is less than 10 (`true`), the `!` flips it, and 5 is in fact 5, so `a != 5` is `false`.
**Question #2** Predict the compiler error: ```rust fn main() { let logged_in = 1; if logged_in { println!("welcome back"); } } ```
Show solution E0308 at the condition: expected `bool`, found integer. `logged_in` is an `i32` (integer literal default), and integers don't pass for bools. The deeper fix is making the variable what it claims to be: `let logged_in = true;`.
**Question #3** Write a function `is_valid_percentage(n: i32) -> bool` that's true when `n` is between 0 and 100 inclusive. (You'll want to wait for lesson 6.5's AND operator... or realize you can do it today with what's on this page and a little nesting. Either answer teaches you something.)
Show solution The lesson-6.5 version will be `n >= 0 && n <= 100`. With today's toolkit only, one honest workaround: ```rust fn is_valid_percentage(n: i32) -> bool { if n < 0 { return false; } n <= 100 } ``` (Using `if` a lesson early; consider it a warm-up lap.) If you wrote the `&&` version because you've seen it elsewhere: also fine, and lesson 6.5 will formalize it.
You now have values that answer questions. Next lesson, programs finally get to *act* on the answers, and Rust's version of `if` comes with a twist you've been prepared for since lesson 1.11.