Step 1 of 6
Two kinds of string: &str and String
Programs are full of text: names, messages, log lines, commands typed by a user. Rust has two main types for text. You've been using one of them since your first println!.
String literals are &str
Every "..." in your code is a string literal. Its type is written &str (read it as "string slice" or "str ref"). The text is stored inside your compiled program, and it can't change:
fn main() {
let greeting: &str = "Hello";
let name = "Ferris"; // also a &str, inferred
println!("{greeting}, {name}!");
}
Hello, Ferris!
String: text you own and can change
A String is a piece of text your program creates while it runs. It can grow, shrink and change. You make one from a literal, from a number, or empty:
fn main() {
let team = String::from("Crabs");
let city = "Lisbon".to_string();
let notes = String::new();
let score = 42;
let score_text = score.to_string();
println!("{team} from {city}, score {score_text}, notes [{notes}]");
}
Crabs from Lisbon, score 42, notes []
String::from("Crabs")and"Lisbon".to_string()do the same thing: they make a newStringholding a copy of the literal's text. Both are common; a team usually picks one style.String::new()makes an emptyString..to_string()works on numbers,chars andbools too. It gives the same text that{}would print.
Why two types?
A String owns its text: it keeps the characters in memory that it manages, which is why it can grow and change. A &str is a view of text that lives somewhere else: inside the program for a literal, or inside a String. Looking at text through a view is cheap, because nothing is copied. Modules 09 to 11 (ownership, borrowing and slices) show exactly how this works. Until then, this rule of thumb covers most code:
- Text written in your code is a
&str. - Text you build, change or keep around is a
String. - A function that only reads text takes a
&strparameter, likefn shout(msg: &str). You can pass it a literal directly:shout("hi"). - A function that creates text returns a
String.
Both kinds print the same way, and the read-only methods in this module (len, contains, to_uppercase, trim...) work on both.
Common mistakes
- Using a literal where a
Stringis expected. The types are different, and Rust doesn't convert silently:
fn main() {
let s: String = "hi";
println!("{s}");
}
error[E0308]: mismatched types
The full message says expected `String`, found `&str` and suggests the fix: "hi".to_string(). The same error appears when a function declared -> String returns a plain "hi".
Your task
Fill in the blanks to turn the literal into a String and the number into text, so the program prints Crabs: 3 wins.
Challenge 2
Fill the blanks: make city a String using the method form, and make note an empty String. The program should print city: Oslo, note: [].
Challenge 3
Write grade(score), which returns the String "pass" when the score is 50 or more and "fail" otherwise.
Returning a plain "pass" won't compile: the function promises a String, and a literal is a &str. Read the error if you try it.