"Dynamically" sized tuples using declarative macros

Below is a declarative macro that allows me to pass "dynamically" size tuples to functions

// src/lib.rs

pub trait Tuple {}

#[macro_export]
macro_rules! tuple {
    ( $( $component:ident ),* ) => {
        impl<$($component),*> Tuple for ($($component),*) {}
    }
}

tuple!(A, B);
tuple!(A, B, C);

One such example of this could be

// src/main.rs

use freight_yard::Tuple;

fn main() {
    is_tuple((1, 2));
    is_tuple((1, 2, 3));
}

fn is_tuple(_tuple: impl Tuple) {}

and over the past hour or so I've been trying to implement the IntoIterator trait which would require some sort of wrapper due to the orphan rule. Like I said there's been a few attempts but to no avail. So my question to anybody reading this that's willing to help how would I go about doing something like that? Oh and in case anybody's curios I'm adding this as a feature to my ECS.

Trying to implement IntoIterator for your tuples? Given that tuples can contain elements with heterogeneous types, this would require some sort of indirection for the IntoIterator::Item associated type, like (I) an enum wrapping all possible types (if only a known and reasonably large subset of types must be supported—something like serde_json::value::Value comes to mind), (II) using a trait object like Box<dyn Value> where Value is some object-safe trait that elements of your tuples must implement, or (III) creating some interface around Box<dyn Any>. Or you could introduce the concept of a homogenous tuple, where all elements are required to have the same type. Although in that case a vector or array might serve the same purpose with less overhead.

1 Like

Sorry I did't make this more clear before the above code is only a basic implementation whereas the real implementation makes items in the tuple implement the Component marker trait.

Can you box the types that implement Component? Then /u/jofas's method would apply (as well as their argument that a vector might be easier :slight_smile: )