为什么这个闭包需要内联或“dyn”? `dyn` 在这里做什么?

2023-11-30

我对下面的生命周期发生了什么感到困惑:

struct Foo{}
impl Foo {
    fn foo(&self, _s: &str) {}
}

fn main() {
    let foo = &Foo{};
    let closure = |s| foo.foo(s);

    // Part 1: error message about wrong lifetime in FnOnce
    take_closure(closure); 

    // Part 2: no error when inlined
    take_closure(|s| foo.foo(s));

    // Part 3: no error when `dyn`d and given explicit signature
    let closure: &dyn Fn(&str) -> _ = &|s| foo.foo(s);
    take_closure(closure);
}

fn take_closure(f: impl Fn(&str) -> ()) {
    let s = get_string();
    f(&s)
}

fn get_string() -> String {
    "".to_string()
}

操场

  1. 为什么第 1 部分会出错?
  2. 为什么第 2 部分没有错误?
  3. 为什么第 3 部分没有出错?第 3 部分实际发生了什么? Rust 会创建 vtable 吗? LLVM 输出的差异为 2 和 3
  4. 有没有更好的办法?内联很丑陋并且dyn既丑陋又让我想知道它到底做了什么。

为什么第 1 部分会出错?

当闭包与它的使用位置分开声明时,Rust 的类型推断不能很好地决定闭包应该具有什么类型。当闭包接受引用时,编译器通常会假设存在一些specific将涉及的生命周期,而不是此处实际需要的“调用者关心提供的任何生命周期”。

事实上,有一个活跃的 Rust RFC 来改善这一点通过添加另一种方法来指定闭包的生命周期参数。 (RFC 还包含一个示例,其中做出相反的寿命假设是行不通的。)

第 3 部分到底发生了什么? Rust 会创建 vtable 吗?

是的,每当你使用时都会涉及到一个vtabledyn。这与这里的根本原因并不是特别相关;只是被忽略的生命周期dyn Fn(&str)以您需要的方式而不是您不需要的方式解决。

有没有更好的办法?内联很丑陋并且dyn既丑陋又让我想知道它到底做了什么。

将闭包直接放置在使用它的函数调用表达式中是very常见的 Rust 风格,我建议您尽可能坚持使用它,因为它也是与类型推断配合良好的方式。

作为需要多次使用闭包的情况下的解决方法,您可以通过限制其类型的函数传递闭包:

fn string_acceptor<F: Fn(&str) -> ()>(f: F) -> F {
    f
}

...

    let foo = &Foo{};
    let closure = string_acceptor(|s| foo.foo(s));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这个闭包需要内联或“dyn”? `dyn` 在这里做什么? 的相关文章

随机推荐

  • 获取scheme中List的中间元素

    我是计划的新手 有人可以给我关于如何获取 列表中的中间元素 的想法吗 这是我的解决方案 它基于一个龟兔赛跑算法 它用于任何需要检测循环列表的列表遍历 因此它不会比正常的列表遍历做更多的工作 define middle elements ls
  • try-catch-finally 错误

    我遇到了问题 最终完成了尝试捕获 我完成了一切正常 直到捕获 我的代码错误都说 预期的 catch 语法错误 我已经进行了谷歌搜索 但没有找到有效的东西 我已附上我的代码 这只是一个放置错误 还是我没有抛出正确类型的错误 提前致谢 publ
  • 如何监视文件中的新内容并检索该内容

    我有一个名为foo txt 该文件包含一些文本 我想实现以下功能 我启动程序 向文件写入一些内容 例如添加一行 new string in foo txt 我只想获取该文件的新内容 您能阐明这个问题的最佳解决方案吗 我还想解决相关问题 如果
  • 如何向 Eclipse 中的 Java 文件添加自定义警告?

    我想添加自定义警告消息 即向 问题 选项卡的 警告 部分添加一个条目 javaEclipse 中的文件 虽然我 在这里和其他地方 找到了有关创建插件和使用标记的信息 但我还没有找到任何有关扩展 问题发现 过程的信息 我发现的大多数文章都没有
  • 在嵌入式系统/微控制器中运行 SQLITE 的最低硬件规格

    我想在嵌入式应用程序中运行 sqlite 能够运行 sqlite 来维护数据库的最低要求是什么 我正在考虑实现 R tree 进行空间搜索 如果我能得到证明这些要求合理的解释 那将会很有帮助 具有大约 32kb 内存的 Cortex M0
  • Java - 找不到符号构造函数

    我对 Java 完全陌生 所以如果我的问题很愚蠢 我很抱歉 我正在做这项作业 我已经阅读主要方法几个小时了 但我就是不明白 我把一些代码放在下面 我可能离这里很远 但我希望完成的是获得启动构造函数的 main 方法 但是当我编译时 我收到一
  • 如何将 gst-rtsp-server 与自己的管道一起使用?

    我正在编写 gstreamer 应用程序 需要通过 rtsp 传输输出音频 视频流 但在gst rtsp server我建立的例子factory创作仅由gst launch syntax factory gst rtsp media fac
  • 在Python中伪造一个cookie来抓取网站

    我尝试抓取的网站使用 js 创建 cookie 我的想法是 我可以在 python 中创建一个 cookie 然后使用该 cookie 来抓取网站 但是 我不知道有什么方法可以做到这一点 有人有什么想法吗 请参见Python httplib
  • 将绘图导出为带有 utf8 字符的 pdf

    当我以 pdf 格式保存绘图时 标签中的 utf8 字符不会出现 当我在 RStudio 中使用 导出 按钮时 它不会出现 当我将此代码包含在具有 pdf 图形输出的 Sweave 文档中时 它不会出现 我的问题是使用 Sweave 而不是
  • Eclipse 可以将 if-else 转换为枚举的切换吗

    ReShaper可以自动识别if枚举上的状态并提供将它们转换为switch声明 或返回 当然 这只有在以下情况下才会发生 if语句仅测试枚举 仅测试其他内容 Eclipse 可以做类似的事情以及如何做吗 为了完整起见 该选项Convert
  • 递归读取 xml 文档并使用正则表达式获取内容

    我有一个如下所示的 xml 文档
  • gdb 拆分视图与代码

    我刚刚在 gdb 中调试一个程序 不知怎的 我发现了一个我以前从未见过甚至听说过的新功能 一个分割视图 除了给出命令之外 我还可以在其中查看和浏览代码 这是什么 我做了什么 或者更具体地说 如何才能再次获得这种分屏模式 这种模式有名称吗 或
  • 我应该在 Visual Studio 中强制转换 void** return 吗

    我用 Visual Studio 9 0 2008 编译了一些代码 行为符合预期 但是当我分配一些带有一些手工制作的二维数组时 函数时 Visual Studio 会生成一些 C4133 警告 void alloc 2d int w int
  • 使用 Retrofit/OkHttp 的 Authenticator 时如何防止并行刷新令牌请求?

    我刚刚偶然发现一个问题 我开始向我构建的后端服务器发送过于并行的刷新令牌请求 这导致了并发问题 其中存在竞争条件 所有这些并行请求同时请求和更新不同的刷新令牌 我想到的唯一解决方案是使用 StateFlow Channel 和无作用域 IO
  • String.Empty 和 ""(空字符串)有什么区别?

    在 NET中 有什么区别String Empty and 它们是否可以互换 或者是否存在一些围绕平等的潜在参考或本地化问题String Empty会保证没有问题吗 In NET prior to version 2 0 creates an
  • 如何用 C# 编写代码以在我的机器上获取直接 X 版本? [复制]

    这个问题在这里已经有答案了 我想知道当用户单击菜单项时他应该能够知道他的机器上安装的直接X版本 我想在 VS2008 中用 C 编写这个代码 我应该在菜单项点击事件中写什么 我是 C 初学者 所以不知道从哪里开始 有人可以帮忙吗 谢谢 这可
  • 在设备上安装应用程序后的 Android 通知 - 如何?

    我想为我的 Android 应用程序添加状态栏通知 安装应用程序后 此通知应显示在状态栏上 我有一个应用程序后台服务 我可以在其中放置通知代码 如何仅在安装应用程序后触发通知 任何解决这个问题的见解都会非常有帮助 Thanks 该规则有一个
  • 在 Byte[] 中创建后检索我的号码

    我想在 Byte 中创建一个基本数字后检索它 public static void main String args throws IOException LinkedList
  • 为什么正则表达式在 Javascript 中使用“match”两次获取值?

    我有以下代码 var str 123 var re 0 9 0 9 2 var found str match re alert found 1 alert found 0 我试图理解为什么 find 0 和 find 1 将包含 123
  • 为什么这个闭包需要内联或“dyn”? `dyn` 在这里做什么?

    我对下面的生命周期发生了什么感到困惑 struct Foo impl Foo fn foo self s str fn main let foo Foo let closure s foo foo s Part 1 error messag