Problem overview
The starting program prints three small profiles. Each has three lines: a name, a language and a pet. The lines are the same in every profile except for the three values:
My name is Andy
I code in Python
I have a dog
My name is Mike
I code in Java
I have a cat
My name is Sarah
I code in JavaScript
I have a parrot
The task is to produce this output with a function called print_messages, which takes the three values as parameters and is called once per person.
Approach
Look for what repeats and what varies. The text "My name is", "I code in" and "I have a" repeats. The name, the language and the animal vary. The repeating text goes inside the function, and the varying values become parameters named name, language and animal.
Nine println! calls become three, plus three function calls. The output stays the same.
The order of the parameters is a design choice, and the calls must follow it. Here it follows the order of the output lines: name, language, animal. Choosing the order that matches how you read the output makes the calls easier to check against the expected text.
Step by step
- Define the function above
mainFunction. Give it three parameters, each typed as an ownedString:name: String, language: String, animal: String. - Print each sentence with
println!, using a{}placeholder for the value. The format string comes first and the parameter follows after a comma. - Call the function three times in
mainFunction, once for each person, passing the values in the same order as the parameters: name, language, animal. - Convert each literal. A literal like
"Andy"is a&str. The parameters wantString, so each argument ends with.to_string().
The solution in Rust
fn print_messages(name: String, language: String, animal: String) {
println!("My name is {}", name);
println!("I code in {}", language);
println!("I have a {}", animal);
}
fn mainFunction() {
print_messages("Andy".to_string(), "Python".to_string(), "dog".to_string());
print_messages("Mike".to_string(), "Java".to_string(), "cat".to_string());
print_messages(
"Sarah".to_string(),
"JavaScript".to_string(),
"parrot".to_string(),
);
}
Details worth knowing:
- Types are required on parameters. Rust does not guess a parameter's type from how it is used, so every parameter is written
name: Type. - The last call is spread over several lines. That is only formatting. Rust ignores line breaks between arguments, and a trailing comma after the last argument is allowed.
- Each call moves its strings. The
Stringvalues created in a call are given to the function. Since nothing uses them afterward, that causes no problem here. - Placeholders and arguments pair up in order. Each
{}in aprintln!format string takes the next argument. Here every line has one placeholder and one argument.
Following one call
Take the second call, print_messages("Mike".to_string(), "Java".to_string(), "cat".to_string()). When it runs, Rust creates the three parameters and gives them the values from the call by position: name becomes "Mike", language becomes "Java" and animal becomes "cat". The first println! fills its placeholder with name and prints My name is Mike. The next two lines do the same with the other two parameters. When the closing brace is reached, the parameters are dropped, and the next call starts with fresh ones.
Why not one function per person?
You could write print_andy(), print_mike() and print_sarah(), but each would contain the same three println! lines, so the repetition would only move. Parameters are what let one body serve every person. The function describes the shape of a profile, and each call supplies the details.
An alternative signature
This lesson takes String parameters, so the caller hands over owned strings. Text that a function only reads can also be taken as &str, which lets the caller pass literals directly with no .to_string(). Both signatures print the same text. The lesson asks for owned String parameters, so the solution uses them.
Common mistakes
- Wrong argument order. All three parameters are
String, so the compiler cannot notice if you pass"dog"first. The output would read "My name is dog". Check the order against the parameter list. - Missing
.to_string(). A bare literal gives a type mismatch, expectedString, found&str. - Wrong number of arguments. A call with two values instead of three is a compile error that names the missing argument.
- Changing the sentences. The text must match exactly, including capitalization and the article in "I have a".
- Printing inside
mainFunctionas well. That duplicates lines. All printing belongs insideprint_messages.
Testing the mistakes
It helps to see what the wrong versions do. With the arguments in the wrong order, the call print_messages("dog".to_string(), "Python".to_string(), "Andy".to_string()) compiles and prints:
My name is dog
I code in Python
I have a Andy
With only two arguments, the compiler refuses to build and reports this function takes 3 arguments but 2 arguments were supplied, noting that argument #3 of type String is missing. A swap is silent, while a missing argument is loud, so read the output as well as the compiler's messages.
Checking your work
Running mainFunction prints the nine lines shown above, three per person. Adding a fourth person now takes one new call and no new println! lines.
