The todo! macro
Sometimes you want to write code in general to help you imagine your project. For example, imagine a simple project to do something with books. Here's what you think as you write it:
struct Book {} // Okay, first I need a book struct. // Nothing in there yet - will add later enum BookType { // A book can be hardcover or softcover, so add an enum HardCover, SoftCover, } fn get_book(book: &Book) -> Option<String> {} // ⚠️ get_book should take a &Book and return an Option<String> fn delete_book(book: Book) -> Result<(), String> {} // delete_book should take a Book and return a Result... // TODO: impl block and make these functions methods... fn check_book_type(book_type: &BookType) { // Let's make sure the match statement works match book_type { BookType::HardCover => println!("It's hardcover"), BookType::SoftCover => println!("It's softcover"), } } fn main() { let book_type = BookType::HardCover; check_book_type(&book_type); // Okay, let's check this function! }
But Rust is not happy with get_book
and delete_book
. It says:
error[E0308]: mismatched types
--> src\main.rs:32:29
|
32 | fn get_book(book: &Book) -> Option<String> {}
| -------- ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
= note: expected enum `std::option::Option<std::string::String>`
found unit type `()`
error[E0308]: mismatched types
--> src\main.rs:34:31
|
34 | fn delete_book(book: Book) -> Result<(), String> {}
| ----------- ^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
= note: expected enum `std::result::Result<(), std::string::String>`
found unit type `()`
But you don't care about get_book
and delete_book
right now. This is where you can use todo!()
. If you add that to the function, Rust will not complain, and will compile.
struct Book {} fn get_book(book: &Book) -> Option<String> { todo!() // todo means "I will do it later, please be quiet" } fn delete_book(book: Book) -> Result<(), String> { todo!() } fn main() {}
So now the code compiles and you can see the result of check_book_type
: It's hardcover
.
But careful, because it only compiles - you can't use the function. If you call a function with todo!()
inside it, it will panic.
Also, todo!()
functions still need real input and output types. If you just write this, it will not compile:
struct Book {} fn get_book(book: &Book) -> WorldsBestType { // ⚠️ todo!() } fn main() {}
It will say:
error[E0412]: cannot find type `WorldsBestType` in this scope
--> src\main.rs:32:29
|
32 | fn get_book(book: &Book) -> WorldsBestType {
| ^^^^^^^^^^^^^^ not found in this scope
todo!()
is actually the same as another macro: unimplemented!()
. Programmers were using unimplemented!()
a lot but it was long to type, so they created todo!()
which is shorter.