Named Parameters in Home
On this page 35
Named parameters allow you to pass arguments to functions by parameter name rather than position, improving code clarity and flexibility.
Table of Contents
- Basic Syntax
- Benefits
- Mixing Positional and Named
- Named-Only Parameters
- With Default Parameters
- Best Practices
Basic Syntax
Calling with Named Arguments
fn create_rect(x: i32, y: i32, width: i32, height: i32): Rect {
Rect { x, y, width, height }
}
// Positional arguments
let r1 = create_rect(10, 20, 100, 50)
// Named arguments
let r2 = create_rect(x: 10, y: 20, width: 100, height: 50)
// Named arguments in any order
let r3 = create_rect(width: 100, height: 50, x: 10, y: 20)
Clarity for Boolean Flags
fn copy_file(source: string, dest: string, overwrite: bool, preserve_metadata: bool): Result<()> {
// ...
}
// Without named arguments - unclear
copy_file("a.txt", "b.txt", true, false) // What do these booleans mean?
// With named arguments - crystal clear
copy_file(
source: "a.txt",
dest: "b.txt",
overwrite: true,
preserve_metadata: false
)
Benefits
1. Self-Documenting Code
// Hard to understand
connect("localhost", 5432, 30, 10, true, false)
// Self-documenting
connect(
host: "localhost",
port: 5432,
timeout: 30,
pool_size: 10,
ssl: true,
auto_reconnect: false
)
2. Skip Optional Parameters
fn draw_text(
text: string,
x: i32 = 0,
y: i32 = 0,
size: i32 = 12,
color: Color = Color::Black,
bold: bool = false,
italic: bool = false
): void {
// ...
}
// Only set specific parameters
draw_text("Hello", x: 100, y: 200, bold: true)
// Without named args, you'd need:
draw_text("Hello", 100, 200, 12, Color::Black, true, false)
3. Prevent Argument Order Mistakes
// Easy to swap arguments
send_email("user@example.com", "admin@example.com", "Subject", "Body")
// Named args prevent mistakes
send_email(
from: "admin@example.com",
to: "user@example.com",
subject: "Subject",
body: "Body"
)
Mixing Positional and Named
Rules for Mixing
- Positional arguments must come first
- Named arguments can follow in any order
- Cannot use positional after named
fn configure(host: string, port: i32, timeout: i32, retries: i32): Config {
Config { host, port, timeout, retries }
}
// ✓ Valid - positional then named
configure("localhost", 8080, timeout: 30, retries: 3)
configure("localhost", 8080, retries: 3, timeout: 30)
// ✓ Valid - all positional
configure("localhost", 8080, 30, 3)
// ✓ Valid - all named
configure(host: "localhost", port: 8080, timeout: 30, retries: 3)
// ✗ Invalid - positional after named
configure(host: "localhost", 8080, 30, 3)
Named-Only Parameters
Separator Syntax
Use _ to mark parameters as named-only:
fn connect(
host: string,
port: i32,
_, // Everything after this is named-only
timeout: i32 = 30,
ssl: bool = false,
verify_cert: bool = true
): Connection {
// ...
}
// ✓ Valid
connect("localhost", 8080)
connect("localhost", 8080, timeout: 60)
connect("localhost", 8080, ssl: true, verify_cert: false)
// ✗ Invalid - can't pass named-only params positionally
connect("localhost", 8080, 60, true, false)
Why Use Named-Only
- Prevent mistakes - Force explicit parameter names
- Future-proof - Can add parameters without breaking calls
- Clarity - Make boolean/config parameters obvious
// Good - flags must be named
fn process_data(
data: string,
_,
validate: bool = true,
transform: bool = true,
cache: bool = false
): Result<Data> {
// ...
}
process_data(data, validate: false, cache: true) // Clear intent
With Default Parameters
Powerful Combination
Named arguments work seamlessly with defaults:
fn create_window(
title: string,
width: i32 = 800,
height: i32 = 600,
_,
resizable: bool = true,
fullscreen: bool = false,
vsync: bool = true,
msaa: i32 = 4
): Window {
// ...
}
// Use defaults for most, customize specific ones
create_window("My App", fullscreen: true)
create_window("My App", width: 1920, height: 1080, vsync: false)
create_window("My App", msaa: 8, resizable: false)
Skip Middle Parameters
fn log(
message: string,
level: LogLevel = LogLevel::Info,
timestamp: bool = true,
color: bool = true,
file: string = "app.log"
): void {
// ...
}
// Skip middle parameters
log("Error occurred", level: LogLevel::Error, file: "errors.log")
log("Debug info", color: false)
Best Practices
1. Use for Configuration
// Good - configuration with named args
fn start_server(
_,
port: i32 = 8080,
workers: i32 = 4,
max_connections: i32 = 1000,
timeout: i32 = 30,
debug: bool = false
): Server {
// ...
}
start_server(port: 3000, debug: true)
2. Use for Boolean Flags
// Good - clear what each flag does
copy_file(
"source.txt",
"dest.txt",
overwrite: true,
preserve_metadata: true,
follow_symlinks: false
)
// Avoid - unclear positional booleans
copy_file("source.txt", "dest.txt", true, true, false)
3. Use for Optional Parameters
// Good - only specify what you need
http_get(
"https://api.example.com/users",
timeout: 60,
headers: custom_headers
)
// Avoid - many None/default values
http_get("https://api.example.com/users", None, None, Some(60), Some(custom_headers), None)
4. Consistent Naming
// Good - consistent parameter names across similar functions
fn read_file(path: string, encoding: string = "utf-8"): Result<string> { }
fn write_file(path: string, content: string, encoding: string = "utf-8"): Result<()> { }
// Both use 'encoding' with same meaning
let content = read_file("data.txt", encoding: "latin1")?
write_file("output.txt", content, encoding: "latin1")?
5. Group Related Parameters
// Good - logical grouping
fn create_button(
text: string,
_,
// Size parameters
width: i32 = 100,
height: i32 = 30,
// Style parameters
color: Color = Color::Blue,
border_width: i32 = 1,
// Behavior parameters
enabled: bool = true,
visible: bool = true
): Button {
// ...
}
Common Patterns
Builder-Style Functions
fn query_builder(
table: string,
_,
columns: Vec<string> = vec!["_"],
where_clause: Option<string> = None,
order_by: Option<string> = None,
limit: Option<i32> = None,
offset: Option<i32> = None
): Query {
// ...
}
let query = query_builder(
"users",
columns: vec!["id", "name", "email"],
where_clause: Some("age > 18"),
order_by: Some("name ASC"),
limit: Some(10)
)
HTTP Requests
fn http_request(
method: string,
url: string,
_,
headers: HashMap<string, string> = HashMap::new(),
body: Option<string> = None,
timeout: i32 = 30,
follow_redirects: bool = true,
verify_ssl: bool = true
): Result<Response> {
// ...
}
http_request(
"POST",
"https://api.example.com/users",
body: Some(json_data),
timeout: 60
)
Database Connections
fn connect_db(
_,
host: string = "localhost",
port: i32 = 5432,
database: string,
username: string,
password: string,
pool_size: i32 = 10,
timeout: i32 = 30,
ssl: bool = false
): Result<Connection> {
// ...
}
connect_db(
database: "myapp",
username: "admin",
password: "secret",
pool_size: 20,
ssl: true
)
Advanced Usage
With Generics
fn create_cache<K, V>(
_,
capacity: usize = 100,
ttl: i32 = 3600,
eviction_policy: EvictionPolicy = EvictionPolicy::LRU
): Cache<K, V> {
// ...
}
let cache = create_cache::<string, User>(
capacity: 1000,
ttl: 7200
)
With Trait Bounds
fn sort_by<T, F>(
items: &mut [T],
compare: F,
_,
reverse: bool = false,
stable: bool = true
): void
where
F: Fn(&T, &T): Ordering
{
// ...
}
sort_by(&mut items, |a, b| a.name.cmp(&b.name), reverse: true)
Forwarding Named Arguments
fn wrapper_function(
data: string,
_,
timeout: i32 = 30,
retries: i32 = 3
): Result<()> {
// Forward named arguments
inner_function(
data,
timeout: timeout,
retries: retries
)
}
Examples
Configuration Function
fn configure_app(
_,
log_level: LogLevel = LogLevel::Info,
log_file: string = "app.log",
port: i32 = 8080,
workers: i32 = 4,
database_url: string,
cache_size: usize = 100,
debug: bool = false
): AppConfig {
AppConfig {
log_level,
log_file,
port,
workers,
database_url,
cache_size,
debug,
}
}
// Easy to see what's being configured
let config = configure_app(
database_url: "postgres://localhost/myapp",
port: 3000,
debug: true,
cache_size: 1000
)
Graphics Function
fn draw_circle(
x: f64,
y: f64,
radius: f64,
_,
fill_color: Color = Color::Black,
stroke_color: Color = Color::Black,
stroke_width: f64 = 1.0,
alpha: f64 = 1.0
): void {
// ...
}
draw_circle(100.0, 100.0, 50.0, fill_color: Color::Red, alpha: 0.5)
Test Assertion
fn assert_response(
response: Response,
_,
status: i32 = 200,
content_type: string = "application/json",
contains: Option<string> = None,
headers: HashMap<string, string> = HashMap::new()
): void {
// ...
}
assert_response(
response,
status: 201,
contains: Some("success"),
headers: hashmap!{"X-Custom" => "value"}
)
See Also
- Default Parameters - Parameter defaults
- Functions - Function definitions
- Variadic Functions - Variable arguments