2016-09-16 7 views
8

के अंदर काम न करने वाले बंद होने पर फ़ंक्शन वापस करने के लिए मैं इसे बंद करने के बिना संकलित करने के लिए नहीं मिल सकता। मैं पहली जगह में सही प्रकार के बंद होने के लिए फ़ंक्शन apply प्राप्त करने का प्रयास कर रहा हूं।मेरे फ़िल्टर

#![feature(conservative_impl_trait)] 
#![allow(dead_code)] 

fn accumulate<'a>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) { 

    // this works 
    let _ = tuples.iter().filter(|t| apply(second, i)(t)); 

    // this doesn't 
    //let f = apply(second, i); 
    //let _ = tuples.iter().filter(f); 

    //this works as well 

    let f = |t: &&(_,_)| apply(second, i)(t); 
    let _ = tuples.iter().filter(f); 
} 

fn apply<A, B, C, F, G>(mut f: F, a: A) -> impl FnMut(B) -> C 
     where F: FnMut(B) -> G, 
       G: FnMut(A) -> C, 
       A: Clone 
{ 
    move |b| f(b)(a.clone()) 
} 


fn second<A, B: ?Sized>(&(_, ref second): &(A, B)) -> &B { 
    second 
} 

fn main() {} 

apply काम करने के लिए मैं क्या कर सकता हूं जैसे मैं इसे चाहता हूं?

+0

मेरे उत्तर के प्रति आपकी प्रतिक्रिया के आधार पर, मेरा सुझाव है कि आप अपनी समस्या का एक [एमसीवीई] तैयार करें। शायद [इस तरह कुछ] (https://play.rust-lang.org/?gist=67472cbead98bdcdb5ea8cd92925130d)। – Shepmaster

+0

मैंने इसे 'लागू' और 'दूसरा' करने के लिए घटा दिया - मैं एचआरटीबी की समस्या को हल करने की कोशिश कर रहा हूं। – iopq

उत्तर

7

सबसे पहले, मुझे यह कहना है कि समस्या impl Trait वाक्यविन्यास के उपयोग से कोई लेना देना नहीं है। मैंने बंद नाम को एक नामित संरचना में परिवर्तित कर दिया और उसी परिणाम प्राप्त किए।

तो, आप करना चाहते हैं के कोड को देखो काम:

let f = apply(second, i); 
let _ = tuples.iter().filter(f); 

क्या संकलक कि बारे में क्या कहना है?

error[E0277]: the trait bound `for<'r> impl std::ops::FnMut<(&(_, _),)>: std::ops::FnMut<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` is not satisfied 
    --> <anon>:11:27 
    | 
11 |  let _ = tuples.iter().filter(f); 
    |       ^^^^^^ trait `for<'r> impl std::ops::FnMut<(&(_, _),)>: std::ops::FnMut<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` not satisfied 

error[E0277]: the trait bound `for<'r> impl std::ops::FnMut<(&(_, _),)>: std::ops::FnOnce<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` is not satisfied 
    --> <anon>:11:27 
    | 
11 |  let _ = tuples.iter().filter(f); 
    |       ^^^^^^ trait `for<'r> impl std::ops::FnMut<(&(_, _),)>: std::ops::FnOnce<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` not satisfied 

ठीक है, तो हमारे पास टाइप एक्स है और इसे विशेषता वाई लागू करने की आवश्यकता है लेकिन ऐसा नहीं है। लेकिन चलो बारीकी से देखें:

for<'r> impl 
std::ops::FnMut<(&(_, _),)>: 
std::ops::FnMut<(&'r &(_, _),)> 

आह हे! filter एक ऐसे फ़ंक्शन की अपेक्षा करता है जो एक संदर्भ को संदर्भित करता है संदर्भ में संदर्भित करता है, जबकि जिस फ़ंक्शन में हम गुजर रहे हैं वह एक ट्यूपल के संदर्भ को स्वीकार करता है। filter एक संदर्भ के संदर्भ को पास करता है क्योंकि tuples.iter() संदर्भों पर पुनरावृत्त करता है, और filter इनके संदर्भों को पास करता है।

ठीक है, के संदर्भ के लिए संदर्भ को स्वीकार करने के second की परिभाषा बदल:

fn second<'a, A, B: ?Sized>(&&(_, ref second): &&'a (A, B)) -> &'a B { 
    second 
} 

संकलक अभी भी खुश नहीं:

error[E0277]: the trait bound `for<'r> impl std::ops::FnMut<(&&(_, _),)>: std::ops::FnMut<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` is not satisfied 
    --> <anon>:11:27 
    | 
11 |  let _ = tuples.iter().filter(f); 
    |       ^^^^^^ trait `for<'r> impl std::ops::FnMut<(&&(_, _),)>: std::ops::FnMut<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>` not satisfied 

error[E0271]: type mismatch resolving `for<'r> <impl std::ops::FnMut<(&&(_, _),)> as std::ops::FnOnce<(&'r &(&str, &std::ops::Fn(i32) -> bool),)>>::Output == bool` 
    --> <anon>:11:27 
    | 
11 |  let _ = tuples.iter().filter(f); 
    |       ^^^^^^ expected bound lifetime parameter , found concrete lifetime 
    | 
    = note: concrete lifetime that was found is lifetime '_#24r 

expected bound lifetime parameter , found concrete lifetime ... कि क्या मतलब है?

f का प्रकार कुछ प्रकार है जो FnMut(&'c &'b (&'a str, &Fn(i32) -> bool)) -> bool लागू करता है। कॉल में apply, B == &'c &'b (&'a str, &Fn(i32) -> bool) और C == bool पर कॉल करें। ध्यान दें कि Bएक निश्चित प्रकार यहां है; 'c एक, निश्चित जीवनकाल का प्रतिनिधित्व करता है, जिसे ठोस जीवनकाल कहा जाता है।

के filter के हस्ताक्षर पर एक नज़र डालें:

fn filter<P>(self, predicate: P) -> Filter<Self, P> where 
    Self: Sized, P: FnMut(&Self::Item) -> bool, 

यहाँ, PFnMut(&Self::Item) -> bool को लागू करना चाहिए। असल में, यह वाक्यविन्यास for<'r> FnMut(&'r Self::Item) -> bool के लिए लघुरूप है। यहाँ। 'r एक बाध्य आजीवन पैरामीटर है।

तो, समस्या हमारे समारोह है कि FnMut(&'c &'b (&'a str, &Fn(i32) -> bool)) -> bool लागू करता नहीं लागू for<'r> FnMut(&'r Self::Item) -> bool करता है। हमें एक ऐसे फ़ंक्शन की आवश्यकता होगी जो for<'c> FnMut(&'c &'b (&'a str, &Fn(i32) -> bool)) -> bool लागू करे।

fn apply<A, B, C, F, G>(mut f: F, a: A) -> impl FnMut(&B) -> C 
     where F: FnMut(&B) -> G, 
       G: FnMut(A) -> C, 
       A: Clone 
{ 
    move |b| f(b)(a.clone()) 
} 

या अधिक स्पष्ट संस्करण: यह करने के लिए एक ही रास्ता है, अब के लिए, apply इस तरह लिखने के लिए होगा

fn apply<A, B, C, F, G>(mut f: F, a: A) -> impl for<'r> FnMut(&'r B) -> C 
     where F: for<'r> FnMut(&'r B) -> G, 
       G: FnMut(A) -> C, 
       A: Clone 
{ 
    move |b| f(b)(a.clone()) 
} 

जंग अंततः higher-kinded types का समर्थन करता है, तो वहाँ एक हो सकता है इस समस्या को हल करने के लिए और अधिक सुरुचिपूर्ण तरीका।

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