- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Rust 中函数接受闭包作为参数或返回闭包的惯用方式是什么?
我认为至少可以通过以下三种方式来完成:
// 1
pub fn run_with_envs_guard1(envs: &HashMap<&str, &str>, f: &dyn FnOnce()) {}
// 2
pub fn run_with_envs_guard2(envs: &HashMap<&str, &str>, f: Box<dyn FnOnce()>) {}
// 3
pub fn run_with_envs_guard3<F: FnOnce()>(envs: &HashMap<&str, &str>, f: F) {}
这三种方式真的有区别吗?如果是,请帮助澄清,我应该选择哪种方式更惯用?
我仍在学习 rust,很抱歉,如果以上所有方法都是一些不好/奇怪的事情。
也许是一个更具体的问题,为什么在1
和2
中我需要dyn
关键字,但在3
中code> 我不知道,据我了解,这些都需要动态调度,是吗?因为实际功能无法在编译时确定
最佳答案
阿卜杜勒回答了你问题的前半部分(我完全同意他所说的),所以我将尝试后半部分。
如果您想从函数返回闭包,则无法返回类型参数,因为这意味着您将返回 any FnOnce
的实例。 ,由调用者选择。您无法返回 &FnOnce
,因为您(通常)需要将所有权传递给调用者。你可以让它与Box<FnOnce>
一起工作,但这往往使用起来很笨拙。当从函数返回闭包时,我偏向 impl
trait syntax .
pub fn test() -> impl FnOnce() {
|| { println!("It worked!") }
}
在参数位置,写 impl FnOnce()
因为某物的类型相当于定义类型参数,正如阿卜杜勒在他的回答中所做的那样。然而,在返回位置,这是一个全新的功能,它返回一个不透明的值。它说“我正在返回一个 FnOnce
,但我不会告诉你它是哪一个”。它与特征对象的概念相同,但没有将其扔进盒子的开销。
回复您的编辑
i don't, from my understanding, these all need dynamic dispatching, is it? as the actual function cannot be determined in compiling time
这实际上不一定是真的。如果您看到dyn
关键字,那么肯定会发生动态(运行时)调度。不过,为了理解您的另一个示例,让我们考虑一个没有 FnOnce
包袱的简单特征。 .
pub trait MyTrait {}
struct Foo;
struct Bar;
impl MyTrait for Foo {}
impl MyTrait for Bar {}
pub fn example<T: MyTrait>(_arg: T) {
println!("It works!");
}
fn main() {
example(Foo);
example(Bar);
}
我声称这里没有发生动态调度。 Rust 使用类型参数对函数进行单态化。这意味着example
就像C++中的模板函数。它的每个实例化最终都会成为一个单独的函数。所以,实际上,在 Rust 编译期间,这最终会更像
struct Foo;
struct Bar;
pub fn example1(_arg: Foo) {
println!("It works!");
}
pub fn example2(_arg: Foo) {
println!("It works!");
}
fn main() {
example1(Foo);
example2(Bar);
}
两个不相关的函数碰巧做了类似的事情。 Rust 静态地解析所有链接,因此运行时不会发生调度。事实上,我们可以证明这一点。获取我刚刚在上面发布的代码,并使用调试符号( rustc -g filename.rs
)对其进行编译。然后使用像 nm
这样的工具(默认情况下在大多数 Linux 机器上可用)列出链接器表中的所有符号。假设您没有打开任何优化,您应该看到两个 example
功能。这就是它们在我的链接器中的样子
0000000000005340 t _ZN10code7example17h46383f9ad372dc94E
00000000000053a0 t _ZN10code7example17h97b400359a146fcaE
或者,与 nm -C
解析函数名称
0000000000005340 t code::example
00000000000053a0 t code::example
两个不同的函数,每个函数都采用特定类型的具体参数。
您的建议FnOnce
会以同样的方式工作。
pub fn run_with_envs_guard3<F: FnOnce()>(envs: &HashMap<&str, &str>, f: F) {}
Rust 中的每个闭包都有不同的类型,因此每次调用此函数时,都会生成 run_with_envs_guard3
的新版本将被制作,专门用于该关闭。该新函数将确切地知道如何处理您刚刚给出的闭包。在 99% 的情况下,如果您打开了优化,这些虚构的本地函数将被内联并优化掉,因此不会造成任何损害。但这里没有动态调度。
在另外两个示例中,我们有 dyn FnOnce
,这更像是您所期望的传统面向对象语言。 dyn FnOnce
包含一个指向某个函数的动态指针,该函数将按照您期望的方式在运行时调度。
关于rust - rust 中函数接受闭包作为参数或返回闭包的惯用方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69956268/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!