2017-08-20 26 views
8

मैं एक फ़ंक्शन लिखने की कोशिश कर रहा हूं जो दो कार्यों को लिखता है, प्रारंभिक डिज़ाइन एक ऐसा फ़ंक्शन है जो दो कार्यों को लेता है और एक रचनात्मक फ़ंक्शन देता है जिसे मैं अन्य कार्यों के साथ लिख सकता हूं, (चूंकि जंग के पास बाकी पैरामीटर नहीं हैं)। लेकिन मैं निराशाजनक गैर-सहायक कंपाइलर त्रुटियों के साथ निर्मित एक लंबी हार्ड दीवार में चला गया हूं।जंग में कार्यों को कैसे लिखें?

मेरे लिखें समारोह:

fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a> 
    where F: 'a + Fn(A) -> B + Sized, G: 'a + Fn(B) -> C + Sized 
{ 
    Box::new(move |x| g(f(x))) 
} 

मैं कैसे करना चाहेंगे इसका इस्तेमाल करने की:

fn main() { 
    let addAndMultiply = compose(|x| x * 2, |x| x + 2); 
    let divideAndSubtract = compose(|x| x/2, |x| x - 2); 

    let finally = compose(*addAndMultiply, *divideAndSubtract); 
    println!("Result is {}", finally(10)); 
} 

rustc उस तरह नहीं है, कोई फर्क नहीं पड़ता कि मैं क्या करने की कोशिश, विशेषता सीमा संतुष्ट कभी नहीं कर रहे हैं। त्रुटि है:

➜ cargo run                                    
    Compiling flowtree v0.1.0 (file:///home/seunlanlege/Projects/flowtree) 
error[E0277]: the trait bound `std::ops::Fn(_) -> _: std::marker::Sized` is not satisfied 
    --> src/main.rs:11:19 
    | 
11 |  let finally = compose(*addAndMultiply, *divideAndSubtract); 
    |     ^^^^^^^ the trait `std::marker::Sized` is not implemented for `std::ops::Fn(_) -> _` 
    | 
    = note: `std::ops::Fn(_) -> _` does not have a constant size known at compile-time 
    = note: required by `compose` 

error[E0277]: the trait bound `std::ops::Fn(_) -> _: std::marker::Sized` is not satisfied 
    --> src/main.rs:11:19 
    | 
11 |  let finally = compose(*addAndMultiply, *divideAndSubtract); 
    |     ^^^^^^^ the trait `std::marker::Sized` is not implemented for `std::ops::Fn(_) -> _` 
    | 
    = note: `std::ops::Fn(_) -> _` does not have a constant size known at compile-time 
    = note: required by `compose` 

error: aborting due to 2 previous errors 

error: Could not compile `flowtree`. 

To learn more, run the command again with --verbose. 
+1

मुख्य लक्ष्य के रूप में, आप इस की तलाश में हो सकता है:: मैं इस उद्देश्य के लिए इस मैक्रो लिखा https://stackoverflow.com/q/36284637/1233251 –

+0

मेरे मामले पर लागू नहीं होता। –

उत्तर

10

@ljedrz points out के रूप में, यह काम आप ही बना कार्यों फिर से संदर्भित करने के लिए की जरूरत बनाने के लिए:

let finally = compose(&*add_and_multiply, &*divide_and_subtract); 

(ध्यान दें कि जंग में, सम्मेलन तय है कि चर नाम snake_case में होना चाहिए)


हालांकि, हम इसे बेहतर बना सकते हैं!

आप, प्रयोगात्मक सुविधाओं का उपयोग करने #![feature(conservative_impl_trait)], जो abstract return types के उपयोग के लिए सक्षम बनाता है तैयार हैं, तो, मदद कर सकते हैं बहुत अपने उदाहरण को आसान बनाने के रूप में यह आप जीवन काल, संदर्भ, Sized की कमी और Box तों को छोड़ कर सकते हैं:

#![feature(conservative_impl_trait)] 

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C 
where 
    F: Fn(A) -> B, 
    G: Fn(B) -> C, 
{ 
    move |x| g(f(x)) 
} 

fn main() { 
    let add_and_multiply = compose(|x| x * 2, |x| x + 2); 
    let divide_and_subtract = compose(|x| x/2, |x| x - 2); 

    let finally = compose(add_and_multiply, divide_and_subtract); 
    println!("Result is {}", finally(10)); 
} 

अंत में, जब से तुम आराम मापदंडों का उल्लेख है, मुझे लगता है कि क्या आप वास्तव में चाहते हैं के लिए एक रास्ता के रूप में कई कार्यों चेन रचना के रूप में आप एक लचीला ढंग से करना चाहते हैं के लिए है।

#![feature(conservative_impl_trait)] 

macro_rules! compose { 
    ($last:expr) => { $last }; 
    ($head:expr, $($tail:expr), +) => { 
     compose_two($head, compose!($($tail),+)) 
    }; 
} 

fn compose_two<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C 
where 
    F: Fn(A) -> B, 
    G: Fn(B) -> C, 
{ 
    move |x| g(f(x)) 
} 

fn main() { 
    let add = |x| x + 2; 
    let multiply = |x| x * 2; 
    let divide = |x| x/2; 
    let intermediate = compose!(add, multiply, divide); 

    let subtract = |x| x - 2; 
    let finally = compose!(intermediate, subtract); 

    println!("Result is {}", finally(10)); 
} 
6

बस finally में संदर्भ जोड़ने और यह काम करेगा:

fn main() { 
    let addAndMultiply = compose(|x| x * 2, |x| x + 2); 
    let divideAndSubtract = compose(|x| x/2, |x| x - 2); 

    let finally = compose(&*addAndMultiply, &*divideAndSubtract); 
    println!("Result is {}", finally(10)); 
} 

अपसंदर्भन addAndMultiply या divideAndSubtract एक विशेषता वस्तु जो Sized नहीं है का खुलासा; इसे Box में लपेटा जाना चाहिए या इसे Sized बाधा वाले फ़ंक्शन में पारित करने के लिए संदर्भित किया जाना चाहिए।

+0

क्या आप समझा सकते हैं कि यह क्यों काम करता है? –

+0

@SeunLanLege यकीन है, किया। – ljedrz

संबंधित मुद्दे