What parameters and arguments are
A function that does one fixed job is limited. Often you want the same code to give different results depending on the input. Parameters are how a function receives that input.
- A parameter is a named placeholder in the function definition.
- An argument is the actual value you pass when you call the function.
In Rust every parameter is written as name: Type. The type is required, and the compiler checks every call against it.
fn say_hello(name: &str, age: i32) {
println!("{}, aged {}", name, age);
}
fn main() {
say_hello("John", 30); // John, aged 30
say_hello("Mary", 26); // Mary, aged 26
}
Arguments are matched to parameters by position: the first argument goes to name, the second to age. Swapping them is a compile error, because 30 is not a &str and "John" is not an i32. Passing too few or too many arguments is also an error.
Owned values and borrowed values
Rust has two common types for text, and the difference matters for parameters.
&stris a borrowed view of text. A string literal such as"Andy"has this type.Stringis owned, growable text."Andy".to_string()orString::from("Andy")creates one.
A parameter of type String takes ownership of the value. The value is moved into the function, and the caller can no longer use it. A parameter of type &str only borrows, so the caller keeps its value. To lend a String without giving it away, pass a reference with &:
fn greet(name: &str) {
println!("Hello {}", name);
}
fn main() {
let name = String::from("Andy");
greet(&name); // lend a reference
println!("{}", name); // still usable: it was only borrowed
}
Passing a plain &str literal where a String is expected does not compile. The compiler reports expected `String`, found `&str` and suggests adding .to_string().
The exercise
The task is to write welcome_user, which takes an owned String called name and prints Welcome, Andy! when given "Andy". Then main_function uses it twice.
- Define the function above
main_function, with the parametername: String. - Print the greeting with
println!("Welcome, {}!", name). Each{}is replaced by the next argument after the format string. The comma, the space and the final!are all part of the expected output. - Call it with a literal. The parameter wants a
Stringbut"Andy"is a&str, so convert it with"Andy".to_string(). - Create a variable with
let name = "John".to_string();. It does not needmut, because it is never changed. - Pass the variable with
welcome_user(name);. This moves theStringinto the function.
fn welcome_user(name: String) {
println!("Welcome, {}!", name);
}
fn main_function() {
welcome_user("Andy".to_string());
let name = "John".to_string();
welcome_user(name);
}
Running these two calls prints:
Welcome, Andy!
Welcome, John!
Gotchas
- Use after move. After
welcome_user(name);, the variablenameis gone. A second callwelcome_user(name);fails withuse of moved value: `name`. If you need the value again, passname.clone()the first time, or change the parameter to&strand pass&name. - Parameters are variables inside the function. The function sees only its own parameters and what it creates itself, not the caller's variables. The caller's
nameand the parameternameare two separate variables that happen to share a name. - Unused parameters. A parameter the body never uses compiles, with a warning, and the function ignores whatever you pass.
Choosing between String and &str
For a function that only reads text, &str is usually the better parameter type, because callers can pass literals directly and can pass a borrowed String with &name. A String parameter makes sense when the function needs to keep or change the text. This lesson uses String on purpose, so you can see ownership move along with the value.
For numbers such as i32 there is no such issue. Simple values like these are copied when passed, so the caller can keep using its variable afterward.
Key takeaways
- Parameters sit in the definition, written
name: Type. Arguments are the values in the call. - Arguments match parameters by position and type, and the compiler checks both.
- A
Stringparameter takes ownership. A&strparameter borrows. - Convert a literal with
.to_string()when the parameter is aString.
