Skip to content

Commit

Permalink
feat: new chapters (operator ? & unrecoverable error) & content impro…
Browse files Browse the repository at this point in the history
…vement
  • Loading branch information
novalagung authored Jul 30, 2024
1 parent d9dfbc1 commit 1220e20
Show file tree
Hide file tree
Showing 29 changed files with 696 additions and 133 deletions.
85 changes: 85 additions & 0 deletions docs-wip/recoverable-error-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
sidebar_position: 55
title: A.55. ErrorRecoverable Error & Error Handling
sidebar_label: A.55. ErrorRecoverable Error & Error Handling
---

Chapter ini merupakan kelanjutan dari chapter sebelumnya tentang pembahasan topic error. Kali ini fokus kita lebih ke **recoverable error** dan penanganannya (error handling).

Rust menganjurkan untuk menggunakan tipe data `Result` untuk penanganan operasi dan data yang berpotensi menghasilkan error. Jadi pastikan telah mempelajari chapter [Tipe DataResult](/basic/result-type) lebih dulu sebelum melanjutkan pembahasan di chapter ini.

--








Operator `?` digunakan untuk meng-*unwrap* data `Option` untuk mengambil nilai `Some<T>`-nya. Penggunaan operator ini adalah alternatif dari penggunaan keyword `match` dengan versi penulisan yang lebih ringkas.

> Operator `?` bisa digunakan pada tipe `Option` maupun [Result](/basic/result-type).

Pada kode berikut kita akan kode sederhana untuk operasi pembagian bilangan random terhadap angka `x`. Silakan praktekan dan pelajari.

```rust
use rand::Rng;

fn main() {
do_compute_random_number_by_x(2);
println!();

do_compute_random_number_by_x(0);
println!();

do_compute_random_number_by_x(10);
}

fn divider(a: i32, b: i32) -> Option<f64> {
if b == 0 {
return None;
}

let result = (a as f64) / (b as f64);
return Some(result);
}

fn do_compute_random_number_by_x(x: i32) {
let n = rand::thread_rng().gen_range(0..100);
println!("calculating {} / {}", n, x);

let result = match divider(n, x) {
None => {
println!(" → WARNING: cannot divide {} by {}", n, x);
0.0
},
Some(x) => x as f64,
};

println!(" → result: {}", result);
}
```

Output program:

![Option type](img/unrecoverable-panic-error-1.png)

Di dalam fungsi `do_compute_random_number_by_x()` terdapat operasi *error handling* menggunakan keyword `match`. Nilai hasil operasi `divider(n, x)` dicek, jika berisi `None` maka pesan *warning* dimunculkan dan nilai `0` dikembalikan. Sebaliknya, maka nilai hasil operasi pembagian dijadikan nilai balik.

Sekarang rubah kode fungsi `do_compute_random_number_by_x()` menjadi seperti ini:

```rust
fn do_compute_random_number_by_x(x: i32) {
let n = rand::thread_rng().gen_range(0..100);
println!("calculating {} / {}", n, x);

let result = divider(n, x)?;

println!(" → result: {}", result);
}
```

Kode tersebut merupakan alternatif penulisan kode fungsi `do_compute_random_number_by_x()` yang didalamnya menerapkan penggunaan operator `?`.

Statement `let result = match divider(n, x) { ... };` beserta isi blok-nya diubah menjadi `let result = divider(n, x)?;`. Perhatikan tanda `?` dibelakang pemanggilan fungsi `divider()`.
1 change: 1 addition & 0 deletions docs/basic/advanced-traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ Lebih detailnya dibahas pada chapter [Attributes](/basic/attributes).

- Pembahasan tentang trait bounds untuk implementasi method kondisional
- Pembahasan tentang trait overloading
- orphan rules

### ◉ Referensi

Expand Down
24 changes: 12 additions & 12 deletions docs/basic/attributes.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
sidebar_position: 50
title: A.50. Attributes
sidebar_label: A.50. Attributes
sidebar_position: 51
title: A.51. Attributes
sidebar_label: A.51. Attributes
---

Kita telah beberapa kali menggunakan attributes pada chapter-chapter sebelumnya, contohnya seperti `#[derive(Debug)]`. Pada chapter ini kita akan bahas tentang apa sebenarnya attributes, macam-macam jenisnya, beserta kegunaannya.

## A.50.1. Konsep attributes
## A.51.1. Konsep attributes

Attributes adalah metadata yang didefinisikan untuk suatu crate, module, atau module item. Kegunaan dari attributes berbeda satu sama lain, tergantung attribute apa yang dipakai (kita akan bahas satu per satu).

Expand Down Expand Up @@ -47,7 +47,7 @@ Sedikit berbeda dengan inner attribute, penulisannya berada di dalam target (cra

Rust mengenal beberapa jenis attributes, dan kita akan membahasnya satu per satu.

## A.50.2. Attribute `derive`
## A.51.2. Attribute `derive`

Attribute `derive` digunakan untuk mempermudah implementasi suatu trait ke tipe data.

Expand Down Expand Up @@ -165,7 +165,7 @@ Bisa dilihat, hasilnya program tereksekusi tanpa error. Enum `Superhero` kini me
- Trait `Debug` via attribute `derive`
- Trait `Display` via implementasi eksplisit

## A.50.3. Attribute `cfg` / *configuration*
## A.51.3. Attribute `cfg` / *configuration*

Attribute `cfg` digunakan untuk operasi-operasi yang berhubungan dengan target arsitekture hardware/prosesor, misalnya seperti conditional compilation ketika OS adalah linux, dan lainnya.

Expand Down Expand Up @@ -328,7 +328,7 @@ Pada profil release, kode program dikompilasi sekaligus dioptimisasi. Penggunaan

Ada beberapa key konfigurasi lainnya yang tersedia. Lebih detailnya silakan lihat di https://doc.rust-lang.org/reference/conditional-compilation.html

## A.50.4. Attribute *linting* & *diagnostic*
## A.51.4. Attribute *linting* & *diagnostic*

Ada beberapa attribute name yang bisa digunakan untuk meng-override *default linting* milik Rust ataupun menandai indikator *diagnostic* lainnya, seperti warning yang muncul karena ada kode yang tidak digunakan, dll; Warning sejenis ini bisa di-override menggunakan attribute.

Expand Down Expand Up @@ -416,7 +416,7 @@ Selain 3 attribute di atas, ada juga beberapa attribute lainnya untuk keperluan
- `#[deprecated]` digunakan untuk menandai bahwa kode di bawahnya adalah *deprecated*.
- `#[must_use]` digunakan untuk mendandai bahwa kode di bawahnya harus digunakan, jika tidak maka akan muncul error.

## A.50.5. Attribute *type system*
## A.51.5. Attribute *type system*

Ada sebuah attribute bernama `non_exhaustive` gunanya untuk mem-*bypass* error yang muncul karena ada pattern matching yang tidak meng-cover semua kondisi, atau untuk mengantisipasi error yang muncul saat deklarasi variabel bertipe struct tapi value property-nya tidak diisi.

Expand Down Expand Up @@ -470,7 +470,7 @@ Pada contoh di atas, tempat di mana enum dideklarasikan dan digunakan adalah mas

> Attribute `non_exhaustive` ini jika digunakan pada struct efeknya saat deklarasi variabel boleh tidak menuliskan value property.

## A.50.6. Attribute *modules*
## A.51.6. Attribute *modules*

Aturan manajemen di Rust cukup ketat, dan sudah dibahas secara mendetal pada chapter [Module SystemModule](/basic/module-basic), yang intinya adalah ada dua cara pembuatan module:

Expand Down Expand Up @@ -530,15 +530,15 @@ Jialankan program, harusnya tidak ada error.

![Attribute](img/attribute-9.png)

## A.50.7. Attribute *testing*
## A.51.7. Attribute *testing*

Lebih detailnya mengenai attribute testing dibahas pada chapter [Testing](#/wip/testing).

## A.50.8. Attribute *macros*
## A.51.8. Attribute *macros*

Lebih detailnya mengenai attribute macros dibahas pada chapter [Macro](#/wip/macro).

## A.50.9 Attribute lainnya
## A.51.9 Attribute lainnya

Rust memiliki cukup banyak attribute yang list-nya bisa dilihat pada link ini https://doc.rust-lang.org/reference/attributes.html.

Expand Down
20 changes: 10 additions & 10 deletions docs/basic/closures.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
sidebar_position: 47
title: A.47. Closures
sidebar_label: A.47. Closures
sidebar_position: 48
title: A.48. Closures
sidebar_label: A.48. Closures
---

Chapter ini membahas tentang closures. Closures sendiri merupakan block fungsi anonimus (anonymous function) yang memiliki kelebihan bisa mengakses item-tem yang posisinya berada di luar block closure tersebut tetapi masih dalam current block scope.

Topik closures sangat erat hubungannya dengan [TraitFunction](/basic/trait-function), namun pada chapter ini pembahasan hanya difokuskan pada bagian penerapan closures saja. Penulis anjurkan untuk lanjut ke chapter berikutnya setelah selesai dengan chapter ini.

## A.47.1. Konsep Closures
## A.48.1. Konsep Closures

Cara penerapan closure sangat mirip seperti fungsi, perbedaannya ada pada notasi penulisan-nya. Agar lebih jelas silakan perhatikan program sederhana di bawah ini.

Expand Down Expand Up @@ -61,7 +61,7 @@ println!("{:.4}", pi); // 3.1416
println!("{pi:.4}"); // 3.1416
```

## A.47.2. Notasi penulisan closure
## A.48.2. Notasi penulisan closure

Closure `calculate_circle_volume_v2` pada contoh di atas adalah salah satu contoh penulisan closure. Sebuah closure bisa memiliki parameter, bisa juga tidak, dan aturan tersebut juga berlaku pada return value.

Expand Down Expand Up @@ -119,7 +119,7 @@ let get_pi = || 3.14;
println!("{:?}", get_pi());
```

## A.47.3. Mutable closure
## A.48.3. Mutable closure

Tidak ada yang spesial mengenai cara mengakses item yang berada di luar block closure. Caranya cukup dengan panggil saja item seperti biasanya.

Expand Down Expand Up @@ -164,7 +164,7 @@ let mut increase_by = |x: i32| {

Keyword `mut` wajib ditambahkan ke variabel penampung closure ketika di dalamnya terdapat operasi perubahan data terhadap variabel yang posisinya di-luar closure. Contohnya bisa dilihat di atas, variabel `num` nilainya di-mutate atau diubah dari dalam closure, karena inilah variabel `increase_by` harus didefinisikan mutable.

## A.47.4. Borrowing pada closure
## A.48.4. Borrowing pada closure

**Semua variabel di luar block closure ketika digunakan di dalam closure maka terjadi operasi borrowing pada variabel tersebut**. Variabel di luar block closure dipinjam agar bisa digunakan di dalam closure.

Expand Down Expand Up @@ -218,7 +218,7 @@ Pada contoh di atas, closure `increase_by` ditambahi parameter baru. Sekarang ad

> Pengaksesan variabel yang berada di luar scope closure tanpa via parameter berarti adalah borrowing, maka dalam penerapannya wajib untuk memperhatikan aturan yang berlaku pada ownership dan borrowing.

## A.47.5. Keyword `move`
## A.48.5. Keyword `move`

Telah dijelaskan di atas bahwa variabel di luar closure, jika diakses dari dalam closure maka terjadi borrowing. Ada cara agar variabel tersebut ownership-nya berpindah ke dalam closure (*move semantics*), yaitu menggunakan keyword `move`.

Expand All @@ -243,7 +243,7 @@ Lalu bagaimana dengan nasib variabel `num` yang berada di luar closure setelah o

Bisa dilihat dari gambar di atas, statement `print` dari dalam block closure hasilnya adalah benar, yaitu `5 + 10 = 15`. Dan variabel `num` di luar block closure tidak berubah nilainya.

## A.47.6. Closure sebagai return type
## A.48.6. Closure sebagai return type

### ◉ Praktik ke-1

Expand Down Expand Up @@ -314,7 +314,7 @@ println!("{message} (from main)");

![Closure](img/closures-5.png)

## A.47.7. Closure sebagai parameter fungsi
## A.48.7. Closure sebagai parameter fungsi

### ◉ Praktik ke-1

Expand Down
24 changes: 12 additions & 12 deletions docs/basic/datetime.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
sidebar_position: 51
title: A.51. Date Time
sidebar_label: A.51. Date Time
sidebar_position: 52
title: A.52. Date Time
sidebar_label: A.52. Date Time
---

Pada chapter ini kita akan mempelajari tentang tipe data datetime yang ada di Rust programming.

Rust menyediakan cukup banyak API untuk keperluan pengolahan datetime, tersedia dalam Standard Library crate. Namun pada chapter ini kita tidak akan menggunakannya, karena yang akan dipakai adalah [`chrono` crate](https://crates.io/crates/chrono) (dianjurkan untuk menggunakan crate ini karena fiturnya lebih banyak).

## A.51.1. Persiapan
## A.52.1. Persiapan

Sebelum memulai pembelajaran, siapkan satu project baru, kemudian tambahkan care `crono` dalam `Cargo.toml`.

Expand All @@ -22,7 +22,7 @@ edition = "2021"
chrono = "0.4.23"
```

## A.51.2. Tipe data `DateTime`
## A.52.2. Tipe data `DateTime`

`crono` menyediakan cukup banyak tipe data untuk merepresentasikan informasi tanggal dan waktu, tetapi yang paling penting untuk diketahui dan dipahami ada dua, yaitu:

Expand All @@ -43,7 +43,7 @@ Sebagai contoh, penulis berlokasi di Jawa Timur, maka ketika ada suatu data bert

Tipe `chrono::naive::datetime::NaiveDateTime` merupakan tipe data datetime yang tidak menyimpan informasi timezone. Nanti akan kita bahas apa kegunaan dari tipe ini.

## A.51.3. Pembuatan objek `DateTime`
## A.52.3. Pembuatan objek `DateTime`

### ◉ Via `Utc::now()`

Expand Down Expand Up @@ -115,7 +115,7 @@ Penerapan method `parse::<DateTime<Utc>>()` sebenarnya mengembalikan tipe data `

Ada beberapa cara lain yang bisa digunakan untuk pembuatan object datetime, dan kita akan bahas juga sebentar lagi.

## A.51.4. `Utc` vs `Local`
## A.52.4. `Utc` vs `Local`

Kesemua cara yang sudah dipelajari di atas juga bisa diterapkan dalam pembuatan object date time dengan timezone offset `Local`. Penerapannya kurang lebih sama, cukup ganti `Utc` menjadi `Local`.

Expand Down Expand Up @@ -160,7 +160,7 @@ sample date 1 (in local_tz): 2023-03-02 16:53:44.562389600 +07:00

Kedua datetime tersebut terpaku **7 jam** persis. Data `2023-03-02 09:53:44` UTC (atau GMT+0), jika dikonversi ke waktu lokal penulis (WIB atau GMT+7) maka akan menjadi `2023-03-02 16:53:44`. Selisihnya sesuai dengan timezone offset, yaitu 7 jam.

## A.51.5. Tipe `NaiveDateTime`
## A.52.5. Tipe `NaiveDateTime`

Rust memilik caranya sendiri dalam pengelolaan data datetime (yang menurut penulis cukup unik). Ada satu tipe data bernama `NaiveDateTime`, yang kegunaannya adalah untuk menampung tipe data datetime **tanpa spesifik timezone offset**.

Expand Down Expand Up @@ -199,7 +199,7 @@ Bisa dilihat pada output di atas, bahwa hasil data datetime berbeda untuk timezo

> Jangan sampai bingung, 2 data datetime di atas tidak sama dan tidak ekuivalen meskipun informasi jam menit detiknya sama persis. Hal ini dikarenakan timezone offset-nya berbeda.

## A.51.6. Konversi datetime UTC ke local timezone, dan sebaliknya
## A.52.6. Konversi datetime UTC ke local timezone, dan sebaliknya

Dalam bekerja dengan tipe data datetime, selalu memperhatikan timezone adalah hal yang sangat penting. Bisa saja dua buah datetime memiliki informasi tanggal dan waktu sama persis, tapi jika timezone-nya berbeda maka keduanya adalah berbeda!

Expand Down Expand Up @@ -231,7 +231,7 @@ Ketiga data datetime di atas adalah ekuivalen:

Data `2023-03-02 10 UTC` jika ditambah 7 jam offset, maka menjadi `2023-03-02 17 GMT+7`.

## A.51.7. UNIX time
## A.52.7. UNIX time

Cara konversi data `DateTime` ke bentuk UNIX time bisa dilakukan lewat 3 cara:

Expand Down Expand Up @@ -264,7 +264,7 @@ Output program di atas:

![DateTime](img/datetime-5.png)

## A.51.8. Date formatting & parsing
## A.52.8. Date formatting & parsing

Konversi datetime ke string (atau biasa disebut dengan date formatting) dilakukan menggunakan method `format` yang dalam penerapannya membutuhkan argument *datetime formatting syntax*.

Expand Down Expand Up @@ -294,7 +294,7 @@ println!("date2 (in string): {}", str_from_date2);
// date2 (in string): 2023-03-01 13:04:00 +0000
```

## A.51.9. DateTime formatting syntax
## A.52.9. DateTime formatting syntax

Berikut adalah tabel formatting syntax untuk tipe data datetime.

Expand Down
Loading

0 comments on commit 1220e20

Please sign in to comment.