> For the complete documentation index, see [llms.txt](https://learning-rust.gitbook.io/book/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://learning-rust.gitbook.io/book/beyond-the-basics/generics.md).

# Generics

> [📖](https://doc.rust-lang.org/beta/book/first-edition/generics.html) Sometimes, when writing a function or data type, we may want it to work for multiple types of arguments. In Rust, we can do this with generics.

💭 The concept is, instead of declaring a specific data type we use an uppercase letter(or CamelCase identifier). ex, **instead x : u8** we use **x : T** . but we have to inform to the compiler that T is a generic type(can be any type) by adding `<T>` at first.

## Generalizing functions

```rust
fn takes_anything<T>(x: T) { // x has type T, T is a generic type
}

fn takes_two_of_the_same_things<T>(x: T, y: T) { // both x and y has same type
}

fn takes_two_things<T, U>(x: T, y: U) { // multiple types
}
```

## Generalizing structs

```rust
struct Point<T> {
  x: T,
  y: T,
}

fn main() {
  let point_a = Point { x: 0, y: 0 }; // T is a int type
  let point_b = Point { x: 0.0, y: 0.0 }; // T is a float type
}

// 🔎 When addding an implementation for a generic struct, the type parameters should be declared after the impl as well
// impl<T> Point<T> {
```

## Generalizing enums

```rust
enum Option<T> {
    Some(T),
    None,
}

enum Result<T, E> {
    Ok(T),
    Err(E),
}
```

> ⭐️ Above [Option](https://doc.rust-lang.org/std/option/index.html) and [Result](https://doc.rust-lang.org/std/result/index.html) types are kind of special generic types which are already defined in Rust’s standard library.
>
> * An **optional value** can have either **Some** value or no value/ **None**.
> * A **result** can represent either success/ **Ok** or failure/ **Err**

### Usages of Option

```rust
// 01 - - - - - - - - - - - - - - - - - - - - - -
fn getIdByUsername(username: &str) -> Option<usize> {
    //if username can be found in the system, set userId
        return Some(userId);
    //else
        None
}

//💭 So on above function, instead of setting return type as usize
// set return type as Option<usize>
//Instead of return userId, return Some(userId)
// else None (💡remember? last return statement no need return keyword and ending ;)

// 02 - - - - - - - - - - - - - - - - - - - - - -
struct Task {
    String,
    assignee: Option<Person>,
}

//💭 Instead of assignee: Person, we use Option<Person>
//Because the task has not been assigned to a specific person

// - - - - - - - - - - - - - - - - - - - - - - -
//when using Option types as return types on functions
// we can use pattern matching to catch the relevant return type(Some/None) when calling them

fn main() {
    let username = "anonymous"
    match getIdByUsername(username) {
        None => println!("User not found"),
        Some(i) => println!("User Id: {}", i)
    }
}
```

### Usages of Result

> [📖](https://doc.rust-lang.org/book/first-edition/error-handling.html) The Option type is a way to use Rust’s type system to express the possibility of absence. Result expresses the possibility of error.

```rust
// - - - - - - - - - - - - - - - - - - - - - -
fn get_word_count_from_file(file_name: &str) -> Result<u32, &str> {
  //if the file is not found on the system, return error
    return Err("File can not be found!")
  //else, count and return the word count
    //let mut word_count: u32; ....
    Ok(word_count)
}

//💭 on above function,
// instead panic(break) the app, when a file can not be found; return Err(something)
// or when it could get the relevant data; return Ok(data)


// - - - - - - - - - - - - - - - - - - - - - - -
// we can use pattern matching to catch the relevant return type(Ok/Err) when calling it

fn main() {
    let mut file_name = "file_a";
    match get_word_count_from_file(file_name) {
        Ok(i) => println!("Word Count: {}", i),
        Err(e) => println!("Error: {}", e)
    }
}
```

> 🔎 Many useful methods have been implemented around Option and Result types. More information can be found on [std::option::Option](https://doc.rust-lang.org/std/option/enum.Option.html) and [std::result::Result](https://doc.rust-lang.org/std/result/enum.Result.html) pages on Rust doc.

⭐️ Also **more practical examples** of options & results can be found on [Error Handling](https://doc.rust-lang.org/book/first-edition/error-handling.html) section in Rust doc.
