So a constant nuisance in strongly-typed languages is functions that take a variable number of args. Usually printing functions like printf()
or println!()
. You can do something like C and have some horrific pile of stack-walking BS, but that's not very satisfying. You can do something like Java or C#, and use reflection and dynamic dispatch a bunch to basically dynamically type some sequence. you can do something like Rust and do compile-time codegen for it. You can do something like, idk what, and just make it a compiler special case.
So I was thinking, what if you had a function that received the varargs in the form of an iterator? What if you could write something like fn foo(x: i32, y: f32, rest: ... (&str, i32))
and it would pass you an impl Iterator<Item = (&str, i32)>
? And then you could call it like foo(1, 2.0, "thing1", 3, "thing2", 4, "thing3", 5)
and it would automatically pair up the args into (&str, i32)
and give you an iterator over them, and error at compile time if you screwed up the count or the types. It's a lot like C# collection initializers in concept, it sugar for giving you varargs as a strongly-typed iterator but it's a pretty flexible iterator.
Then of course as I'm talking about this Vi just straight up whips out https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=454577b11d0cf781f704bf3a8f77f010, which is based on https://docs.rs/frunk/latest/frunk/. Vi's impl need syntax sugar but that's kinda what this is all about... But it's quite literally a heterogenously-typed list that's evaluated at compile time. I didn't think that was possible without macros.
So uh now I have two interesting options to play with I guess!
Per #36 , the question to ask yourself is "how can you iterate over a heterogenous tuple?" Vi's example does it by basically turning it into a homogenous list of type
impl Display
. #36 does it by compile-time code gen where the compiler knows it can iterate over a tuple and match (one way or another) on different types.
she who will not be named keeps advocating for dependent types for this. XD The problem with deptypes is compiling them to efficient, essentially-unmanaged native code. If we had a GC and a JIT it would be much more appealing.