【问题标题】:How can you figure out the type signature of (a reference to) a function?你怎么能弄清楚(引用)一个函数的类型签名?
【发布时间】:2015-01-26 16:02:12
【问题描述】:

我想测试一个函数的一些实现。为了清楚地做到这一点,我想将对它们的引用放入一个数组中并一个一个地调用它们。由于最近的语法更改,为此,您需要首先将函数显式转换为具有正确类型签名的函数引用。由于您用于声明函数的语法与其实际类型不同,因此这是一项非常重要的任务。

如何确定对具有非平凡签名的 Rust 函数的引用类型(例如,它涉及泛型、生命周期、采用另一个函数等)?

用签名声明了一个特定的function(我写的):

pub fn take_while2<'a,T,F:Fn(&T)->bool >(initial: &'a [T], predicate: F) -> Option<&'a [T]> {...}

【问题讨论】:

    标签: rust type-signature


    【解决方案1】:

    你不能,至少,没有那个功能。

    首先,你不能有一个泛型变量。也就是说,x 不能依赖于T。举个更简单的例子:

    fn test<T>(_: &T) { unimplemented!() }
    
    fn main() {
        let x: fn(&u8) = test;
    }
    

    这是可行的,因为编译器可以推断出具体类型 T 是(在本例中为 u8)。那你为什么不能这样做呢?因为F。您要求的是闭包类型,而闭包类型是匿名;无论你做什么,你都无法说出一个名字。如果你设法让类型系统推断闭包类型,那么它只对exactly一个特定的闭包有效。就像函数一样,每个闭包都有自己独特的类型,即使它字面意思是相同的。与函数不同,闭包没有可以使用的通用基类型。

    在不知道您实际想要完成什么的情况下,很难给出任何建议。但是,要在黑暗中尝试一下,您可能想尝试以下方法:

    pub fn take_while2<'a,T>(initial: &'a [T], predicate: Box<Fn(&T) -> bool>) -> Option<&'a [T]> { // '
        // ...
    }
    
    fn main() {
        let functions: Vec<for<'a> fn(&'a [u8], Box<Fn(&u8) -> bool>) -> Option<&'a [u8]>> = vec![take_while2]; // '
        // ...
    }
    

    注意for&lt;'a&gt; 的使用,这是一个更高级别的生命周期,它与take_while2 定义的'a 通用参数具有相同的功能。 另外请注意,此语法不适用于类型参数。

    感谢 Shepmaster 提醒我您可以使用&amp;Fn(&amp;T) -&gt; bool 而不是盒装封口。这提高了调用者堆分配的要求。

    这还需要您将要传递给predicate 的任何闭包装箱。

    【讨论】:

    • 你也可以接受一个 trait 对象作为引用 (&amp;Fn(&amp;T) -&gt; bool) 而不需要堆分配。
    • @Shepmaster:你知道,我完全忘记了这些。 到 Editmobile!
    • 非常感谢您的详尽回答!不过,我需要一段时间才能理解到底发生了什么。在 alpha 的准备阶段,铁锈复杂地从我头上飞过。 Fn 是您用 fn 声明的函数的类型吗?一个人在盒子里意味着什么?这是否意味着每次调用函数时局部变量都分配在堆上?
    • @AndrewWagner:函数具有fn 类型。 FnFnMutFnOnce 是三个“可调用”特征,它们由您可以调用的事物实现,包括函数和闭包。拳击确实把它放在了堆上。基本上,您不能按值使用特征,因此您需要 某种 间接性,无论是盒子还是借用的参考。评论有点多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 2011-02-28
    • 2017-09-11
    相关资源
    最近更新 更多