3.4 KiB
Syntax
Don’t jump ahead!
Complete the exercise for the previous section before you start this
one.
It’s located in exercises/01_intro/00_welcome, in the course
GitHub’s repository.
Use wr
to start the course and verify your solutions.
The previous task doesn’t even qualify as an exercise, but it already
exposed you to quite a bit of Rust syntax. We won’t
cover every single detail of Rust’s syntax used in the previous
exercise. Instead, we’ll 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 commentFunctions
Functions in Rust are defined using the fn keyword,
followed by the function’s name, its input parameters, and its return
type. The function’s 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
doesn’t return anything (i.e. if it returns (), Rust’s unit
type). That’s 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 function’s 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 we’ve been mentioned “types” a few times, let’s 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 can’t add a string to a
number, but you can add two numbers together. If leveraged correctly,
types can prevent whole classes of runtime bugs.