假设我有一个接受回调的函数
fn foo<T>(callback: impl FnOnce(T) -> T, value: T) -> T {
callback(value)
}
假设我现在想让这个回调函数成为可选函数,在我看来,最明显的方法就是使用Option
:
fn foo<T>(callback: Option<impl FnOnce(T) -> T>, value: T) -> T {
if let Some(callback) = callback {
callback(value)
} else {
value
}
}
然而,当这样做时,我在使用站点遇到了一个问题。例如,下面的代码不能编译:
fn bar() -> u8 {
let value: u8 = b'.';
let value = foo(None, value);
value
}
出现以下错误:
error[E0282]: type annotations needed
--> XX:XX:XX
|
XX | let value = foo(None, value);
| ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
|
help: consider specifying the generic argument
|
XX | let value = foo(None::<T>, value);
| +++++
For more information about this error, try `rustc --explain E0282`.
但是,似乎不可能为此提供类型,因为impl …
语法在这里不能用作类型参数,而且无论如何都需要闭包中的具体类型。
是否可以像这样注解缺少闭包的类型?
3条答案
按热度按时间sd2nnvve1#
你必须给它提供一个实现
FnOnce(u8) -> u8
的类型,因为这是foo
所需要的,我能想到的最简单的一个是函数指针:eoigrqb62#
有几种方法。你需要选择一个实现
FnOnce(T) -> T
的类型。对于示例,我将使用fn(T) -> T
,但它没有太大区别:foo
上使用turbofish:eufgjt7s3#
作为现有答案的替代方案,提供一个恒等函数(返回其参数的函数)将是更合适的函数风格,其优点是可以解决整个问题,而且它还可能表现得更好,因为没有任何分支可以被错误地预测。
换句话说,使用
Option
实际上是“浪费”,因为“没有函数”会导致与“恒等函数”相同的可观察行为。(Of当然,
|v| v
比identity
短,所以使用哪一个是一个品味问题。)这并没有解决当恒等函数不应该导致和没有函数一样的行为时,如何在可选函数的上下文中指定
None
的一般问题。其他答案解决了如何处理这种情况。这个答案旨在当两种情况 * 确实 * 具有相同的行为时提供更好的解决方案。