【问题标题】:Can a function return a closure taking String arguments and return values?函数可以返回带有字符串参数和返回值的闭包吗?
【发布时间】:2016-10-06 21:56:15
【问题描述】:

如果我返回一个这样定义的闭包:

fn closure_thing() -> (Fn(String) -> String) {
    |thing| {
        thing[1..4]
    }
}

我收到以下错误:

= note: `std::ops::Fn(std::string::String) -> std::string::String + 'static` does not have a constant size known at compile-time
= note: the return type of a function must have a statically known size`

我也试过Fn(&String) -> &String。闭包有没有一种简单的方法可以将字符串作为参数并返回一个字符串?

【问题讨论】:

    标签: rust closures


    【解决方案1】:

    Fn 是一个特征。你不能返回一个特征。你可以返回一个函数指针:

    fn closure_thing() -> (fn(String) -> String) {
        fn foo(thing: String) -> String {
            …
        }
    
        foo
    }
    

    您也可以返回Box

    fn closure_thing() -> Box<Fn(String) -> String> {
        Box::new(|thing| {
            …
        })
    }
    

    但是那个有运行时成本,所以应该考虑作为最后的手段。

    正如@Veedrac 所说,您也可以使用impl Trait

    #![feature(conservative_impl_trait)]
    
    fn closure_thing() -> impl Fn(String) -> String {
        |thing| {
            …
        }
    }
    

    但是从 Rust 1.12 开始,它还不稳定,需要一个夜间编译器。它允许您返回任何特征,而无需先前解决方案的运行时成本。

    【讨论】:

    • 您的前两个也有(潜在的)运行时成本,因为它们涉及动态调度。 AFAIK 唯一的解决方案是使用impl Trait
    • 你可能应该提到你的第一个例子不能直接工作,因为闭包不会持续足够长的时间(除非我错过了什么)。
    • @ErikVesteraas TIL borrowck 在“未找到主函数”之后运行,这是一个致命错误
    • @mcarton by runtime cost,你的意思是堆分配的成本吗?或者还有其他与 rust's Box 有关的东西?
    • @JeffQuick 成本是一次堆分配+每次调用函数时的动态调度。正如@veedrac 提到的,如果可以接受每晚工作,-&gt; impl Trait 也是一个解决方案。
    【解决方案2】:

    函数的返回类型必须具有静态已知的大小

    实现这一点的一种方法是装箱...

    fn closure_thing() -> Box<Fn(String) -> String> {
        Box::new(|thing| {
            (&thing[1..4]).to_string()
        })
    }
    

    请注意,我还将结果转换为 String.. 因为切片将返回 str

    正如 mcarton 所指出的,装箱会产生堆分配的运行时成本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 2015-02-03
      • 2011-05-20
      相关资源
      最近更新 更多