The todo! macro

Terkadang Anda ingin menulis code secara general (menggunakan pseudocode) untuk membantu Anda membayangkan proyek Anda. Sebagai contoh, bayangkan sebuah proyek sederhana untuk melakukan sesuatu yang berhubungan dengan buku. Kira-kira, mungkin seperti inilah yang Anda pikirkan:

struct Book {} // Okay, pertama, saya memerlukan sebuah struct bernama Book.
               // Belum ada apapun di dalamnya - kita akan menambahkannya kemudian

enum BookType { // Sebuah buku bisa dalam bentuk hardcover atau softcover, sehingga kita tambahkan enum
    HardCover,
    SoftCover,
}

fn get_book(book: &Book) -> Option<String> {} // ⚠️ get_book mengambil &Book dan mengembalikan Option<String>

fn delete_book(book: Book) -> Result<(), String> {} // delete_book mengambil Book sebagai inputannya dan mengembalikan Result...
                                                    // TODO: block impl dan buat sebuah method dengan function ini ...
fn check_book_type(book_type: &BookType) { // Mari kita pastikan bahwa statement matchnya bekerja
    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, kita periksa function ini!
}

Tapi Rust akan memberikan teguran pada function get_book dan delete_book. Compiler mengatakan:

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 `()`

Tapi untuk sekarang ini kita belum begitu peduli dengan function get_book dan delete_book. Inilah dimana kita bisa menggunakan todo!(). Jika kita menambahkannya pada function, Rust tidak akan menganggapnya sebagai error, dan programnya dikompilasi tanpa hambatan apapun.

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() {}

Sekarang codenya bisa di-compile dan Anda bisa melihat hasil dari function check_book_type: It's hardcover.

Tapi, bukan berarti saat codenya ter-compile maka Anda bisa menggunakan functionnya. Anda tidak bisa menggunakannya. Jika Anda panggil function yang berisi todo!() didalamnya, maka ia akan panic.

Juga, function todo!() tetap memerlukan type pada input dan outputnya. Jika Anda menuliskannya seperti dibawah ini, maka ia tidak akan ter-compile:

struct Book {}

fn get_book(book: &Book) -> WorldsBestType { // ⚠️
    todo!()
}

fn main() {}

Compiler akan memberikan pesan:

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!() sebenarnya sama seperti macro yang unimplemented!(). Programmers sangat sering menggunakan unimplemented!(), namun ia terlalu panjang untuk diketik. Jadinya, dibuatlah todo!() dimana ia adalah versi pendeknya.