rust - 如何将元组作为参数传递以便在稳定的 Rust 中顺序应用具有多个返回值的函数?

标签 rust tuples traits

我想弄清楚如何在 Rust 中按顺序应用两个函数,其中第一个函数返回一个元组。所以像这样:

let f = |x,y| { x+y; };
let g = || (1,2);
println("{}", f(g()));

这行不通。即使用 2 元素元组替换 g()

在 Julia 中,我可以执行 f(g()...) 将元组扩展为函数参数。

我想我可以定义一个 .apply 方法来为我做扩展。以下工作,但必须手动或通过为每个参数数量编写的宏:

trait Apply2<A,B,C>: Fn(A,B) -> C {
    fn apply(&self, _ :(A, B)) -> C;
}

impl<T,A,B,C> Apply2<A,B,C> for T where T: Fn(A,B) -> C {
    fn apply(&self, (a, b) : (A, B)) -> C {
        self(a, b)
    }
}

// and then…

println!("{}", f.apply(g()));

但是,手动/基于宏的特征和实现的编写有些痛苦。我想这也应该有效:

trait Apply<Args>: Fn<Args> {
    fn apply(&self, _ :Args) -> Self::Output;
}

impl<T,A,B> Apply<(A,B)> for T where T: Fn<(A,B)> {
    fn apply(&self, (a, b) : (A, B)) -> Self::Output {
        self(a, b)
    }
}

但是,这在“稳定版”中是不允许的,此时我不会切换到夜间构建。

有什么更好的主意吗? Rust 有什么计划可以更好地处理这种情况?

最佳答案

你不能在稳定版中完全做到这一点,但你可以用宏覆盖大部分功能:

trait Apply<Args> {
    type Output;
    fn apply(&self, args: Args) -> Self::Output;
}

macro_rules! impl_apply {
    // Empty case
    () => {};
    ($first_generic:ident $($other_generics:ident)*) => {
        impl_apply!($($other_generics)*);

        impl<$first_generic, $($other_generics,)* Ret, Func>
            Apply<($first_generic, $($other_generics,)*)>
            for Func
        where
            Func: Fn($first_generic, $($other_generics,)*) -> Ret,
        {
            type Output = Ret;
            #[allow(non_snake_case)]
            fn apply(
                &self,
                ($first_generic, $($other_generics,)*): ($first_generic, $($other_generics,)*),
            ) -> Self::Output {
                self($first_generic, $($other_generics,)*)
            }
        }
    };
}
impl<Ret, Func> Apply<()> for Func
where
    Func: Fn() -> Ret,
{
    type Output = Ret;
    fn apply(&self, (): ()) -> Self::Output {
        self()
    }
}
impl_apply!(A B C D E F G H I J K L M);

Playground .

这个宏涵盖了最多 13 个参数的所有函数。

关于rust - 如何将元组作为参数传递以便在稳定的 Rust 中顺序应用具有多个返回值的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70470356/

相关文章:

rust - 引用向量中的元素

unicode - 解析和导航 UTF-8 字节流的惯用方法

rust - 如何借用一个字段进行序列化,但在反序列化时创建它?

c++ - 将 map<double, tuple<double, double>> 复制到 map<double, double> 没有循环?

c++ - 通过使用显式构造函数将相同的参数传递给每个元素来构造元组

python - 获取特质听众列表——谁在听我的特质?

python - 内存使用 @on_trait_change 与 _foo_changed()

rust - 如何找到 Linux 主目录的路径?

python - 元组在赋值中解包

rust - 特征对象的静态数组