# Strings

* `String` can be mutated.
* `&str` borrowed, immutable string slice.
* References:
  * [Strings](https://doc.rust-lang.org/book/ch08-02-strings.html)

## strings1.rs

```rust
// TODO: Fix the compiler error without changing the function signature.
fn current_favorite_color() -> String {
    String::from("blue")
}

fn main() {
    let answer = current_favorite_color();
    println!("My current favorite color is {answer}");
}
```

* In this exercise the function is expecting `String` as return type but got `&str` instead.
* `"hello"` is `&str` and we just need to convert it into `String`.
* We can use either one of below expressions:

  ```rust
  String::from("blue")
  "blue".to_string()
  ```

## strings2.rs

```rust
// TODO: Fix the compiler error in the `main` function without changing this function.
fn is_a_color_word(attempt: &str) -> bool {
    attempt == "green" || attempt == "blue" || attempt == "red"
}

fn main() {
    let word = String::from("green"); // Don't change this line.

    if is_a_color_word(&word) {
        println!("That is a color word I know!");
    } else {
        println!("That is not a color word I know.");
    }
}
```

* Similar problem with previous exercise.
* The function is expecting `&str` but got `String` instead.
* So we can convert it using either codes below:

  ```rust
  is_a_color_word(&word)
  is_a_color_word(word.as_str())
  ```

## strings3.rs

```rust
fn trim_me(input: &str) -> &str {
    // TODO: Remove whitespace from both ends of a string.
    input.trim()
}

fn compose_me(input: &str) -> String {
    // TODO: Add " world!" to the string! There are multiple ways to do this.
    format!("{input} world!")
}

fn replace_me(input: &str) -> String {
    // TODO: Replace "cars" in the string with "balloons".
    input.replace("cars", "balloons")
}

fn main() {
    // You can optionally experiment here.
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn trim_a_string() {
        assert_eq!(trim_me("Hello!     "), "Hello!");
        assert_eq!(trim_me("  What's up!"), "What's up!");
        assert_eq!(trim_me("   Hola!  "), "Hola!");
    }

    #[test]
    fn compose_a_string() {
        assert_eq!(compose_me("Hello"), "Hello world!");
        assert_eq!(compose_me("Goodbye"), "Goodbye world!");
    }

    #[test]
    fn replace_a_string() {
        assert_eq!(
            replace_me("I think cars are cool"),
            "I think balloons are cool",
        );
        assert_eq!(
            replace_me("I love to look at cars"),
            "I love to look at balloons",
        );
    }
}
```

* In this exercise we have 3 task.
* First is to trim given `&str` in function `trim_me` and return `&str`.
  * We can use `trim` method to do this.
* Second is to add `" world!"` into given `&str` in function `compose_me`.
  * We have multiple option to do this.
  * But because `&str` is immutable we cannot just simply use `+`.
  * We can either convert it into `String` first or use `format` macro like below.

    ```rust
    format!("{input} world!")
    input.to_string() + " world!"
    ```
* Last is to replace occurrence of `cars` to `balloons` in function `replace_me`.
  * We can do this by using `replace` method.

## strings4.rs

```rust
// Calls of this function should be replaced with calls of `string_slice` or `string`.
fn placeholder() {}

fn string_slice(arg: &str) {
    println!("{arg}");
}

fn string(arg: String) {
    println!("{arg}");
}

// TODO: Here are a bunch of values - some are `String`, some are `&str`.
// Your task is to replace `placeholder(…)` with either `string_slice(…)`
// or `string(…)` depending on what you think each value is.
fn main() {
    string_slice("blue");

    string("red".to_string());

    string(String::from("hi"));

    string("rust is fun!".to_owned());

    string("nice weather".into());

    string(format!("Interpolation {}", "Station"));

    // WARNING: This is byte indexing, not character indexing.
    // Character indexing can be done using `s.chars().nth(INDEX)`.
    string_slice(&String::from("abc")[0..1]);

    string_slice("  hello there ".trim());

    string("Happy Monday!".replace("Mon", "Tues"));

    string("mY sHiFt KeY iS sTiCkY".to_lowercase());
}
```

* In this exercise we need to replace `placeholder` with either `string` or `string_slice` for given parameters.
* I explain each of the line below:

  ```rust
  // "blue" is &str
  string_slice("blue");
  // to_string() return String
  string("red".to_string());
  // String
  string(String::from("hi"));
  // to_owned() return String
  string("rust is fun!".to_owned());
  // Here, both answers work.
  // `.into()` converts a type into an expected type.
  // If it is called where `String` is expected, it will convert `&str` to `String`.
  string("nice weather".into());
  // format return String
  string(format!("Interpolation {}", "Station"));
  // &str because it a slice
  string_slice(&String::from("abc")[0..1]);
  // trim return &str
  string_slice("  hello there ".trim());
  // replace return String
  string("Happy Monday!".replace("Mon", "Tues"));
  // to_lowercase() return String
  string("mY sHiFt KeY iS sTiCkY".to_lowercase());
  ```
* Basically anything that require string manipulation usually return `String` and if no string manipulation usually return `&str`


---

# 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://bagus-cahyono.gitbook.io/programming-notes/rust/rustlings_exercise/09_strings.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.
