# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learning-rust.gitbook.io/book/beyond-the-basics/generics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
