2016-06-01 17 views
5

znalazłem this discussion o krotki splatting, ale jest od 2014 rokuTuple ikona/zastosowanie w Rust

Podany przykład jest:

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

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

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

a proponowane rozwiązanie jest toczyć własną apply funkcję:

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()); 
} 

Czy to jest obecnie najlepszy sposób, aby przejść? Jeśli tak, to jaka jest prawidłowa składnia? Pojawiają się błędy, w tym expected type, found | at line 1 col 20 używając powyższych.

Czy nadal nie ma operatora krotki?

Odpowiedz

6

Nie sądzę, że istnieje operator splat.

Kod znaleziony w 2014 r. Pochodzi sprzed rdzy 1.0, więc jest nieaktualny. Aby uczynić pracę apply funkcji w wątku 1,0 Rust, zmienić go, co następuje:

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); 
} 

Ten kod kompiluje i działa poprawnie na the Rust playground.

Można alternatywnie użyć f(t.0, t.1) jako ciało apply lub destructure tam na liście parametrów (Playground):

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

Udowodnienie negatyw jest zawsze dość trudne ...

O ile mi wiadomo, nie jest w istocie żaden operator krotka ikona. Jednak rodzina cech Fn* przyjmuje pojedynczy argument, jako krotkę.

Na nocnej kompilatora, aktywując niektóre niestabilne funkcje, można więc używać:

#![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); 
} 

Nie zbyt idealne, ale w przypadku braku wsparcia dla variadics, zawsze trzeba znać liczbę elementów twoja krotka i tak wartość jest niska.

3

Oto wersja apply że działa dla krotek o rozmiarach od 1 do 6 (może być zwiększona) (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,} 

Zastanawiam się stworzyć skrzynkę dla tego. Jeśli to zrobię, wstawię tutaj link.