在Rust中模拟可变通用类型是否可能?

huangapple go评论99阅读模式
英文:

Is it possible to emulate variadic generics in Rust?

问题

Rust缺少可变泛型(以及可变函数)作为一种语言特性。

由于它不直接支持这些,是否可以以某种方式模拟这种行为?

我怀疑这可能可以通过宏来实现,但我还没有对它们有详细的了解,所以我还不能提出一个设计建议。

英文:

Rust is missing Variadic Generics (and also variadic functions) as a language feature.

Since it doesn't directly support these, is it possible to emulate the behavior in some way?

I suspect this might be possible with macros, but I don't have a detailed understanding of them (yet) so I can't (yet) sketch out a design suggestion.

答案1

得分: 1

根据您的要求,这是翻译好的内容:

"As stated in the comments, maybe this is not, in the end, what you need.
But in case this can help, here are two trivial examples of variadic macro.

One considers the variable arguments as a whole (as the content of an array), another explicitly considers each argument separately thanks to (compile-time) recursion.

Note that these examples only intend to illustrate the idea.
They are very bad since they make strong choices about the involved types and do not even consider what happens in terms of ownership (borrowing/moving).

The details about the syntax and logic for such kind of declarative macros can be found in this document."

macro_rules! i32_addition {
    ($($values:expr),*) => {
        [$($values),*].iter().sum::<i32>()
    };
}

macro_rules! text_addition {
    ($value:expr) => {
        $value.to_string()
    };
    ($head:expr, $($tail:expr),*) => {
        $head.to_string() + &text_addition!($($tail),*)
    };
}

fn main() {
    let r1 = i32_addition!(1, 2, 3, 5, 7);
    println!("{:?}", r1);
    let r2 = i32_addition!(1, 2, 3, 5, 7, 11, 13);
    println!("{:?}", r2);
    let r3 = text_addition!("1", "2", "3", "5", "7");
    println!("{:?}", r3);
    let r4 = text_addition!("1", "2", "3", "5", "7", "11", "13");
    println!("{:?}", r4);
}
/*
18
42
"12357"
"123571113"
*/
英文:

As stated in the comments, maybe this is not, in the end, what you need.
But in case this can help, here are two trivial examples of variadic macro.

One considers the variable arguments as a whole (as the content of an array), another explicitly considers each argument separately thanks to (compile-time) recursion.

Note that these examples only intend to illustrate the idea.
They are very bad since they make strong choices about the involved types and do not even consider what happens in terms of ownership (borrowing/moving).

The details about the syntax and logic for such kind of declarative macros can be found in this document.

macro_rules! i32_addition {
    ($($values:expr),*) =&gt; {
        [$($values),*].iter().sum::&lt;i32&gt;()
    };
}

macro_rules! text_addition {
    ($value:expr) =&gt; {
        $value.to_string()
    };
    ($head:expr, $($tail:expr),*) =&gt; {
        $head.to_string() + &amp;text_addition!($($tail),*)
    };
}

fn main() {
    let r1 = i32_addition!(1, 2, 3, 5, 7);
    println!(&quot;{:?}&quot;, r1);
    let r2 = i32_addition!(1, 2, 3, 5, 7, 11, 13);
    println!(&quot;{:?}&quot;, r2);
    let r3 = text_addition!(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;5&quot;, &quot;7&quot;);
    println!(&quot;{:?}&quot;, r3);
    let r4 = text_addition!(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;5&quot;, &quot;7&quot;, &quot;11&quot;, &quot;13&quot;);
    println!(&quot;{:?}&quot;, r4);
}
/*
18
42
&quot;12357&quot;
&quot;123571113&quot;
*/

答案2

得分: 0

如果您不想自己编写宏,可以使用一个包含异构列表的crate:frunk

struct Variadic<H: HList> {
  xs: H,
}
英文:

If you don't want to write the macros yourself, there's a crate with heterogenous lists: frunk

struct Variadic&lt;H: HList&gt; {
  xs: H,
}

huangapple
  • 本文由 发表于 2023年5月28日 16:09:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定