Problem overview
The quiz shows two functions and asks what the code prints:
fn welcome_user() {
println!("Hey coder!");
}
fn main_function() {
println!("Welcome back!");
welcome_user();
}
The options are: A, Hey coder! then Welcome back!; B, only Welcome back!; C, errors; D, Welcome back! then Hey coder!. As in the other quizzes of this chapter, main_function is the main part of the program, the code that runs. The answer is recorded in a comment and printed with println!.
Approach: follow the flow of execution
Execution flow means the order in which statements run. Inside a function body it is top to bottom. When a statement is a call to another function, the flow jumps into that function, runs its body, then returns to the line after the call.
Walk through it:
- Definitions.
welcome_userandmain_functionare only defined. Nothing prints yet. - First statement of
main_function.println!("Welcome back!");runs. The output so far isWelcome back!. - Second statement.
welcome_user();is a call. The flow jumps intowelcome_userand runsprintln!("Hey coder!");. The output is nowWelcome back!and thenHey coder!. - Return. The body of
welcome_userends, control returns tomain_function, and there are no more statements.
That is option D.
Why the others fail
- A reverses the order. It would be right if the call came before the print in
main_function. - B forgets the call.
welcome_user();does run, and its message appears. - C has no basis in the code. The definitions are valid, and the call uses a function that exists. The quiz's two functions are written one after the other at the top level, and the order of two top-level definitions does not matter.
A way to check yourself
Keep a running list of the output and add to it each time a println! actually runs. When you reach a call, pause the current function, trace the called function completely, then come back. Here the list goes Welcome back! and then, from inside the call, Hey coder!. The same technique works for any chain of calls, however deep. If welcome_user itself called a third function, you would trace that one completely before returning to welcome_user.
The solution in Rust
// answer = "D"
println!("D");
/* Explanation:
We first only define the welcome_user() function, so the println!("Hey coder!") won't actually be executed for now.
The main_function() is our "main program" so all the statements inside there will be executed in the order they are written.
First one is the "println!("Welcome back!");", which will be executed and the output so far is:
Welcome back!
Then, the "welcome_user();" function call will be executed.
So the code inside the function body (println!("Hey coder!");) will get executed now and the output is:
Welcome back!
Hey coder!
*/
Rust details:
- Layout does not decide the order. In Rust, indentation and blank lines do not change what runs. The order of statements inside the braces does. In the quiz,
welcome_useris defined first, but it prints second, because it is called second. - A call inside a body is a statement.
welcome_user();ends with a semicolon and, once it finishes, the next statement continues. - Entry point. A complete Rust program starts in a function named
main. The quiz calls its main partmain_function, and the lesson's tests only read the letter you print.
Edge cases and common mistakes
- Thinking the first-defined function runs first. Definition order is not execution order. The flow is decided by what is called, and when.
- Forgetting to return. After a called function ends, the flow continues after the call. With one more line, such as
println!("Bye!");afterwelcome_user();, the output would beWelcome back!,Hey coder!,Bye!. - Dropping the called function's output. Output from inside a called function appears at the point of the call, not at the end of the program.
- Letter mismatch. The comment and the printed letter should both be
D.
