元组splat /适用于Rust

时间:2016-06-01 09:06:17

标签: tuples rust

我发现了this discussion关于元组字符集的问题,但它是从2014年开始的。

给出的例子是:

fn sum(x: i32, y: i32) -> i32 {
    x + y
}

fn prepare_args () -> (i32, i32) {
    (1, 2)
}

fn main() {
    sum(prepare_args()); // Doesn't work
}

建议的解决方案是推出自己的apply函数:

fn apply<A,B,C>(f: |A,B|->C, t: (A,B)) -> C {
    let (a,b) = t;
    f(a,b)
}

fn main() {
    apply(sum, prepare_args());
}

这是目前最好的方式吗?如果是这样,这里的语法是什么?我使用上述内容包括expected type, found | at line 1 col 20,但我收到了一些错误。

是否仍然没有元组splat运算符?

3 个答案:

答案 0 :(得分:6)

我认为没有splat运营商。

您从2014年发现的代码来自Rust 1.0之前,因此它已过时。要使apply函数在1.0之后的Rust中运行,请将其更改为以下内容:

fn sum(x: i32, y: i32) -> i32 {
    x + y
}

fn prepare_args() -> (i32, i32) {
    (1, 2)
}

fn apply<A, B, C, F>(f: F, t: (A, B)) -> C
    where F : Fn(A, B) -> C
{
    let (a, b) = t;
    f(a, b)
}

fn main() {
    let x = apply(sum, prepare_args());
    println!("{}", x);
}

此代码在the Rust playground上正确编译并运行。

您也可以使用f(t.0, t.1)作为apply的正文,或者在参数列表(Playground)中进行解构:

fn apply<A, B, C, F>(f: F, (a, b): (A, B)) -> C
    where F : Fn(A, B) -> C
{
    f(a, b)
}

答案 1 :(得分:5)

证明否定总是很难......

据我所知,确实没有元组splat运算符。但是,Fn*特征族(Fn)只需要一个参数作为元组。

在夜间编译器上,激活一些不稳定的功能,您可以使用:

#![feature(fn_traits)]
#![feature(unboxed_closures)]

fn sum(x: i32, y: i32) -> i32 {
    x + y
}

fn prepare_args () -> (i32, i32) {
    (1, 2)
}

fn main() {
    let func: &Fn(i32, i32) -> i32 = &sum;
    let result = func.call(prepare_args());
    println!("{:?}", result);
}

不太理想,但是在没有对变量的支持的情况下,你总是需要知道元组元素的数量,所以值很低。

答案 2 :(得分:3)

以下版本apply适用于尺寸从1到6(可以增加)的元组(Playground):

fn main() {
    let add1 = |x| x + 1;
    let sum2 = ::std::ops::Add::add;
    let sum3 = |a, b, c| a + b + c;
    assert_eq!(apply(add1, (1,)), 2);
    assert_eq!(apply(sum2, (1, 2)), 3);
    assert_eq!(apply(sum3, (1, 2, 3)), 6);
}

#[inline(always)]
pub fn apply<Fun, In, Out>(fun: Fun, params: In) -> Out
    where ApplyImpl: Apply<Fun, In, Out>
{
    ApplyImpl::apply(fun, params)
}

pub trait Apply<Fun, In, Out> {
    fn apply(fun: Fun, params: In) -> Out;
}

pub struct ApplyImpl;

macro_rules! impl_apply {
    () => ();
    ($A:ident, $($B:ident,)*) => (
        impl_apply!{$($B,)*}

        impl<$A, $($B,)* Fun, Out> Apply<Fun, ($A, $($B),*), Out> for ApplyImpl
        where Fun: Fn($A, $($B),*) -> Out
        {
            #[allow(non_snake_case)]
            #[inline(always)]
            fn apply(fun: Fun, params: ($A, $($B),*)) -> Out {
                // use type parameters as var names...
                let ($A, $($B),*) = params;
                fun($A, $($B),*)
            }
        }
    )
}

impl_apply!{A, B, C, D, E, F,}

我正在考虑为它创造一个箱子。如果我这样做,我会把链接放在这里。