In Rust, how can you make a function that takes any number of parameters of any type?

Kristian Kristola

Kristian Kristola

· 5 min read
flutter

Photo by Martin Rancourt on Unsplash

 

In Rust, you can define functions that can take a varying number of parameters with a recursive macro. Though, to be specific, that will make them macros and not functions. But nevertheless, you can call them in a similar way as you would call a function.

In Rust, you can define macros multiple times and the compiler will use the first definition that matches the input:

macro_rules! print_types {
    ($one_and_only_param:expr) => {
        $one_and_only_param.print();
    };
    ($first_param:expr, $($rest_of_params:expr),+) => {
        $first_param.print();
        print_types!($($rest_of_params),+);
    };
}

In this case, the first macro will match if there is only one parameter. In other cases, when there are more parameters, the second macro will match.

This macro is recursive, because it will call itself again and again, with one less parameter every time, until there's only one left, at which point the first macro will match.

So if you call it like this:

fn main() {
    print_types!(123, "glxblt", 900);
}

First it will expand to this:

// Automatically generated by compiler:
123.print();
print_types!("glxblt", 900);

And then this:

// Automatically generated by compiler:
123.print();
"glxblt".print();
print_types!(900);

And finally this:

// Automatically generated by compiler:
123.print();
"glxblt".print();
900.print();

In Rust, macros don't know anything about variable types. Variable types exist on semantic level (i.e. what does the code mean). Whereas macros operate on syntactic level (i.e. what does the code look like). In order to detect the type of variable, you can use a trait:

trait Print {
    fn print(&self);
}

impl Print for i32 {
    fn print(&self) {
        println!("param type: i32, value: {}", self);
    }
}

impl Print for str {
    fn print(&self) {
        println!("param type: str, value: {}", self);
    }
}

Now our code is done and we can run it, which will print:

param type: i32, value: 123
param type: str, value: glxblt
param type: i32, value: 900
Kristian Kristola

About Kristian Kristola

I'm a consultant and software developer with a strong foundation in game programming and the ability to adapt to new technologies and languages. Please feel free to contact me at:@
Copyright © 2024 Kiuas Games. All rights reserved.
Made by Osuuskunta Kiuas Games

This website uses Google Analytics to collect anonymous information such as the number of visitors to different pages.