Files
100-exercises-to-learn-rust/book/src/01_intro/01_syntax.md
LukeMathWalker 4401743807 Formatter
2024-05-24 18:16:20 +02:00

3.4 KiB
Raw Blame History

Syntax

Dont jump ahead!
Complete the exercise for the previous section before you start this one.
Its located in exercises/01_intro/00_welcome, in the course GitHubs repository.
Use wr to start the course and verify your solutions.

The previous task doesnt even qualify as an exercise, but it already exposed you to quite a bit of Rust syntax. We wont cover every single detail of Rusts syntax used in the previous exercise. Instead, well cover just enough to keep going without getting stuck in the details.
One step at a time!

Comments

You can use // for single-line comments:

// This is a single-line comment
// Followed by another single-line comment

Functions

Functions in Rust are defined using the fn keyword, followed by the functions name, its input parameters, and its return type. The functions body is enclosed in curly braces {}.

In previous exercise, you saw the greeting function:

// `fn` <function_name> ( <input parameters> ) -> <return_type> { <body> }
fn greeting() -> &'static str {
    // TODO: fix me 👇
    "I'm ready to __!"
}

greeting has no input parameters and returns a reference to a string slice (&'static str).

Return type

The return type can be omitted from the signature if the function doesnt return anything (i.e. if it returns (), Rusts unit type). Thats what happened with the test_welcome function:

fn test_welcome() {
    assert_eq!(greeting(), "I'm ready to learn Rust!");
}

The above is equivalent to:

// Spelling out the unit return type explicitly
//                   👇
fn test_welcome() -> () {
    assert_eq!(greeting(), "I'm ready to learn Rust!");
}

Returning values

The last expression in a function is implicitly returned:

fn greeting() -> &'static str {
    // This is the last expression in the function
    // Therefore its value is returned by `greeting`
    "I'm ready to learn Rust!"
}

You can also use the return keyword to return a value early:

fn greeting() -> &'static str {
    // Notice the semicolon at the end of the line!
    return "I'm ready to learn Rust!";
}

It is considered idiomatic to omit the return keyword when possible.

Input parameters

Input parameters are declared inside the parentheses () that follow the functions name.
Each parameter is declared with its name, followed by a colon :, followed by its type.

For example, the greet function below takes a name parameter of type &str (a “string slice”):

// An input parameter
//        👇
fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

If there are multiple input parameters, they must be separated with commas.

Type annotations

Since weve been mentioned “types” a few times, lets state it clearly: Rust is a statically typed language.
Every single value in Rust has a type and that type must be known to the compiler at compile-time.

Types are a form of static analysis.
You can think of a type as a tag that the compiler attaches to every value in your program. Depending on the tag, the compiler can enforce different rules—e.g. you cant add a string to a number, but you can add two numbers together. If leveraged correctly, types can prevent whole classes of runtime bugs.