Variable number of different type arguments?

Hello,
Right now, I have this hypothetical case (ignore the main function). Now, I want to make a function called "run" or something that takes a variable number of arguments, each of a different type (the type of arguments or number of arguments is variable, however, the the type of each argument is known to implement the trait "Stuff"). Then, it calls the respective "yell" function for that argument. For the actual application of this, I have possibly 15 different types, and the # of arguments varies between 1 to 5, so simply making multiple variants of each function is impractical. Any ideas?

Thanks,
ndrewxie

fn run<T: Stuff>(t: T) { t.yell() }
fn run_2<T: Stuff, U: Stuff>(t: T, u: U) {
    t.yell();
    u.yell();
}

Something like this?

That's what I thought, but the real application I'm using it for has like 15 different types, and the # of arguments range from 1 to 5, inclusive (so around 813615 different functions!). Gonna be a nightmare to mantain or create it that way lmao

By any chance is this on nightly? And do you feel adventurous?

Which one, the actual project? Yeah, I can do it on nightly. I try to stay off of it because some nightly features are not planned to be stabilized at all, though (from what I've read, some nightly features forever stay only on nightly).

Well, if you are using generic functions, you only need to create one for each number of arguments, so 5 functions.

You can also use macros, if that's easier.

2 Likes

Yeah, true, makes sense. Yeah, I'll do that. Thanks! 5 seems doable

I would probably go with macros as @RustyYato says, but in the case you want to be very flexible on how you implement it, you could in theory go the custom Fn impl over generic types, to end up with a variety of possibilities.

An example is my submission to the Squeeze challenge.

euh... a little too fancy for me :wink:
Yeah @RustyYato's solution solved the problem

1 Like

Sorry for a semi - necropost, but my problem wasn’t quite solved. I need to return one of the 1-5 arguments the function takes, and each of those arguments have potentially different types. I don’t think impl trait is a good way, because I need to get a concrete type from the return value.
Thanks,
Ndrewxie

Why not use an enum?

enum Five<T, U, W, X, Z> {
    One(T),
    Two(U),
    Three(W),
    Four(X),
    Five(Z)
}

fn for_five<T, U, W, X, Z>(a: T, b: U, c: W, d: X, e: Z) -> Five<T, U, W, X, Z> {
    //Your code
}
fn for_four<T, U, W, X>(a: T, b: U, c: W, d: X) -> Five<T, U, W, X, ()> {
   //Your code
}
//Etc...
1 Like

I was considering that.... but that might be a little clunky. If there's no better solution, yeah I'll just go with that.

If an enum is too clunky then use macros

I'm not very familiar with macros, could you please give me a high level explanation on how I would do it? Thanks,
ndrewxie

Sure, could you give the function implementation for 3 arguments, and I'll try and convert it to a macro.

Could you, then, take a &[&dyn Stuff]?

fn yell_lots(x: &[&dyn Stuff]) {
    for x in x {
        x.yell();
    }
}

fn main() {
    yell_lots(&[&123, &123.456, &456]);
}

That's a bit noisier in callers, but avoids all the macros/enums/etc stuff.

1 Like

Sorry about the mistake, I suppose my example code wasn't very accurate. What I really want to do is given a variable number of arguments, each argument implementing a certain trait (if that helps), and return one of the arguments depending on a certain criterea.

That seems like a very promising solution. Thanks!

1 Like

What's the return type you're expecting this will produce? Because if it's not a trait object, you'll need another enum (like either, but with more options...)

Nevermind, I'm going with the enum option. Thanks to OptimisticPeach for the idea.

2 Likes