How to print the don’t-care symbol?

Hello,
Is it possible to print a don’t-care symbol?

fn main() {
    let _= 12;
        }

Thank you.

1 Like

I'm not sure I understand the question. You can print an underscore character directly:

print!("_");

You can't print the value after the assignment, because it's already gone. If you need this for print-debugging, you can use the dbg! macro to print the value of any¹ expression in-line without altering the rest of the code.

let _ = dbg!(12);

Alternatively, you can name the variable with a leading underscore. This will suppress unused-variable warnings if the print is removed but otherwise act like a normal variable assignment²:

let _a = 12;
print!("{_a}");

¹ As long as the result type of the expression implements Debug

² Note that this will change when drop() is called vs. let _ = ..., so you need to be careful when doing this with things like Mutex guards.

9 Likes

It's important to understand that _ is not a variable (as it would be in Python or Lua). It is a special syntax which immediately drops the value.

14 Likes

Hello,
Thank you so much for your reply.
What is the usage of the don’t-care symbol?

There's a couple of common scenarios:

  • Some types, like Result, are marked with a #[must_use] annotation because ignoring them usually indicates a bug in your program. let _ = ... will suppress the resulting warning because you're explicitly discarding the value.
  • When destructuring a compound type, you sometimes don't need all of the components. let (_, a) = fn_returning_a_tuple();, for instance, will discard the first tuple element and store the second in a.
3 Likes

In Rust _ is the so called "wildcard pattern" Patterns - The Rust Reference

3 Likes

Hello,
How can I access to _=12?

You can't.

3 Likes

Hello,
Thank you so much for your reply.
So, what is the benefit of the don’t-care symbol?

See @2e71828's answer.

In more detail, _ explicitly doesn't bind anything, which means that place expressions on the right aren't moved, if it's a temporary it drops immediately, it doesn't count as a use to the borrow checker, and so on. Sometimes this has a semantic meaning to your code, like when something has a destructor, or in a destructuring assignment or match statement where you want to bind some fields but not others, etc.

Here's an example involving temporaries, for example.

1 Like

And here's another example involving the borrow checker.

3 Likes

The benefit is that you can tell the compiler you don't care. If you don't care, you won't need to print it. If you need to print it, then you care. (Btw, you've only asked about the value in an l-value position, where it means “don't bind”. In a pattern, it means “matches anything” and in a type position, it means “infer this” — two other flavors of “dear compiler, I don't care”.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.