【问题标题】:Figuring out return type of closure确定闭包的返回类型
【发布时间】:2015-08-18 21:46:00
【问题描述】:

在以下示例中,我无法确定 fn filter 函数的类型签名。

Node 和 Descendant 定义仅用于语法。它不是为了做任何事情!

use std::iter::Filter;

#[derive(Clone)]
pub struct Node<'a> {
   s: &'a str,
}

pub struct Descendants<'a>{
    iter: Node<'a>
}

impl<'a> Iterator for Descendants<'a> {
    type Item = Node<'a>;

    fn next(&mut self) -> Option<Node<'a>> {
        Some(Node {s: self.iter.s})
    }
}

impl<'a> Node<'a> {
    pub fn descendants(&self) -> Descendants<'a> {
        Descendants{ iter: Node{s: self.s} }  
    }

    pub fn filter(&self, criteria: &str) -> Filter<Descendants<'a>, fn(&'a Node<'a>)->bool > {
        self.descendants()
            .filter(|node| node.s == "meh")
    }
}

fn main() {
    let doc = Node{s: "str"};

}

(Playground link)

我得到的错误如下:

<anon>:27:28: 27:34 error: the type of this value must be known in this context
<anon>:27             .filter(|node| node.s == "meh")
                                     ^~~~~~
<anon>:27:21: 27:43 error: mismatched types:
 expected `fn(&Node<'_>) -> bool`,
    found `[closure <anon>:27:21: 27:43]`
(expected fn pointer,
    found closure) [E0308]
<anon>:27             .filter(|node| node.s == "meh")
                              ^~~~~~~~~~~~~~~~~~~~~~
<anon>:27:14: 27:44 error: type mismatch: the type `fn(&Node<'_>) -> bool` implements the trait `core::ops::FnMut<(&Node<'_>,)>`, but the trait `for<'r> core::ops::FnMut<(&'r Node<'_>,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]
<anon>:27             .filter(|node| node.s == "meh")
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:27:14: 27:44 error: type mismatch resolving `for<'r> <fn(&Node<'_>) -> bool as core::ops::FnOnce<(&'r Node<'_>,)>>::Output == bool`:
 expected bound lifetime parameter ,
    found concrete lifetime [E0271]
<anon>:27             .filter(|node| node.s == "meh")
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 4 previous errors
playpen: application terminated with error code 101

当我根据这个问题Correct way to return an Iterator? 尝试用pub fn filter(&amp;self, criteria: &amp;str) -&gt; () 替换pub fn filter(&amp;self, criteria: &amp;str) -&gt; Filter&lt;Descendants&lt;'a&gt;, fn(&amp;'a Node&lt;'a&gt;)-&gt;bool &gt; 我得到

<anon>:26:9: 27:44 error: mismatched types:
 expected `()`,
    found `core::iter::Filter<Descendants<'_>, [closure <anon>:27:21: 27:43]>`

我应该用什么替换closure

或者,如果返回 Filter 太难和挑剔,我该如何为 fn filter() 返回类型编写 Wrapper

【问题讨论】:

    标签: iterator rust


    【解决方案1】:

    我清楚地记得这个问题之前已经回答过几次(我什至在回答 a few minutes before 中写过这个问题)但我现在找不到链接,所以就在这里。

    您的代码的问题是您使用闭包作为filter() 参数:

    .filter(|node| node.s == "meh")
    

    Rust 中未装箱的闭包被实现为匿名类型,自然无法命名,因此没有方法可以编写返回使用闭包的迭代器的函数签名。这就是您收到的错误消息的内容:

     expected `fn(&Node<'_>) -> bool`,
        found `[closure <anon>:27:21: 27:43]`
    (expected fn pointer,
        found closure) [E0308]
    

    有几种方法可以解决这个问题,其中一种是使用 trait 对象:

    pub fn filter<'b>(&'b self, criteria: &'b str) -> Box<Iterator<Item=Node<'a>+'b>>
    {
        Box::new(self.descendants().filter(move |node| node.s == criteria))
    }
    

    鉴于您的闭包具有非空环境,这是您的代码工作的唯一方法。如果你的闭包没有捕获任何东西,你可以使用一个可以写出类型的静态函数:

    pub fn filter(&self) -> Filter<Descendants<'a>, fn(&Node<'a>) -> bool> {
        fn filter_fn<'b>(node: &Node<'b>) -> bool {
            node.s == "meh"
        }
        self.descendants().filter(filter_fn)
    }
    

    【讨论】:

    • 旁注,如果filter_fn/closure 必须采用另一个参数怎么办?比如说Vec&lt;i32&gt;
    • filter_fn() 和闭包都不能接受额外的参数,因为它不再对应于filter() 签名。您可以在闭包中捕获 Vec&lt;i32&gt;,例如move |node| node.s.len() == vector.head().unwrap_or(12) as usize,但这与在我的第一个示例中捕获criteria 没有什么不同。
    猜你喜欢
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    相关资源
    最近更新 更多