有没有办法让 Rust 闭包只将一些变量移入其中?

     2023-02-22     115

关键词:

【中文标题】有没有办法让 Rust 闭包只将一些变量移入其中?【英文标题】:Is there a way to have a Rust closure that moves only some variables into it? 【发布时间】:2020-02-15 23:16:27 【问题描述】:

我有一个通用的 struct 设置和一个额外的变量设置,我想调整和玩弄。

对于整数范围内的所有可能值,我想启动一个(作用域)线程,将此变量设置为该值。根据这个值,它们做的工作略有不同。

这些线程中的每一个都应该能够读取常规设置结构。

use crossbeam; // 0.7.3

struct Settings 
    // ... many fields


const MAX_FEASIBLE_SCORE: u8 = 10;

fn example(settings: Settings) 
    crossbeam::scope(|scope| 
        for score in 0..MAX_FEASIBLE_SCORE 
            scope.spawn(|_| 
                let work_result = do_cool_computation(&settings, score);
                println!(":?", work_result);
            );
        
    )
    .unwrap();


fn do_cool_computation(_: &Settings, _: u8) 

这不会编译:

error[E0373]: closure may outlive the current function, but it borrows `score`, which is owned by the current function
  --> src/lib.rs:12:25
   |
10 |     crossbeam::scope(|scope| 
   |                       ----- has type `&crossbeam_utils::thread::Scope<'1>`
11 |         for score in 0..MAX_FEASIBLE_SCORE 
12 |             scope.spawn(|_| 
   |                         ^^^ may outlive borrowed value `score`
13 |                 let work_result = do_cool_computation(&settings, score);
   |                                                                  ----- `score` is borrowed here
   |
note: function requires argument type to outlive `'1`
  --> src/lib.rs:12:13
   |
12 | /             scope.spawn(|_| 
13 | |                 let work_result = do_cool_computation(&settings, score);
14 | |                 println!(":?", work_result);
15 | |             );
   | |______________^
help: to force the closure to take ownership of `score` (and any other referenced variables), use the `move` keyword
   |
12 |             scope.spawn(move |_| 
   |                         ^^^^^^^^

这将使&amp;settings 无效,因为第一个循环迭代将在move 闭包中取得settings 的所有权。

使其工作的唯一简单方法是:

Settings 结构复制到每个线程中(在我的实际应用程序中这是相当昂贵的) 在settings周围引入一个Arc,也觉得有点可惜。

有什么方法可以绕过引用计数吗?有没有办法可以将score 移动到内部闭包中,同时仍然允许引用settings

【问题讨论】:

【参考方案1】:

closure! macro 提供了选择性地将变量引用、移动或克隆到闭包中的能力。

来自文档的示例:

use closure::closure;

let string = "move".to_string();
let x = 10;
let mut y = 20;
let rc = Rc::new(5);

let closure = closure!(move string, ref x, ref mut y, clone rc, |arg: i32| 
    ...
);

已捕获但未列出的变量默认被移动。

【讨论】:

【参考方案2】:

是的,可以只将一个或一些变量移动到闭包中(而不是全部或一个都没有)。

是的,这可以用来“规避”引用计数。

我在rayon::scope 的文档中找到了一个答案,该答案正是关于这个问题的:“[从范围内的线程范围内] 访问堆栈数据”。该页面还有一个比这个问题中的伪代码更清晰的示例。

事实证明,您可以:

使用move 闭包,但通过用引用遮蔽它们来引用外部作用域中的变量,因此使用let settings = &amp;settings 通过引用而不是值来捕获它们:

crossbeam::scope(|scope| 
    let settings = &settings; // refer to outer variable by reference
    for score in 0..MAX_FEASIBLE_SCORE 
        scope.spawn(move |_| 
            let work_result = do_cool_computation(settings, score);
            println!(":?", work_result);
        );
    
)
.unwrap();

使用普通闭包,并且仅通过使用 let score = score 将所需变量隐藏在闭包内来移动所需变量:

crossbeam::scope(|scope| 
    for score in 0..MAX_FEASIBLE_SCORE 
        scope.spawn(|_| 
            let score = score; // capture only score
            let work_result = do_cool_computation(&settings, score);
            println!(":?", work_result);
        );
    
)
.unwrap();

【讨论】:

这里是极小的吹毛求疵,但你并没有真正“规避”任何事情,你只是不是引用计数。 @trentcl 谢谢!你当然是对的。 “规避”在这里可能有点草率。我稍微改变了答案中的书写方式,但如果您有更好的建议使其更清晰,请随时提出一个(和/或自己直接编辑答案) Your second answer does not work.

有没有办法在 Rust 库中包含二进制或文本文件?

】有没有办法在Rust库中包含二进制或文本文件?【英文标题】:IsthereanywaytoincludebinaryortextfilesinaRustlibrary?【发布时间】:2015-12-2107:44:50【问题描述】:我正在尝试创建一个库,并且我想在其中包含一些二进制(或文本)文件,... 查看详情

有没有办法从使用提供的 rust 中的 &str 类型获取函数指针

】有没有办法从使用提供的rust中的&str类型获取函数指针【英文标题】:Isthereanywaytogetafunctionpointerfroma&strtypeinrustwhichisprovidedbytheuse【发布时间】:2022-01-2113:02:27【问题描述】:。示例:use提供了一个函数的名称​​用户提... 查看详情

rust学习--变量(代码片段)

...?说一下我的理解。这个特性可以规避掉很多问题,比如一些常见的低级逻辑错误。更重要的是,这个特性会影响到多线程并发编程。变量不再可变,就不存在临界资源问题,也就不需要引入锁,这会影响到使用者对并发模型的... 查看详情

有没有办法让父链接排除一些子元素?

】有没有办法让父链接排除一些子元素?【英文标题】:IsthereawaytomaketheparentLinkexcludesomechildelements?【发布时间】:2019-12-1515:55:08【问题描述】:所以我的列表的每一行都有一个Link,它打开了一个弹出窗口。其中有复制按钮和另... 查看详情

在 Rust 中,有没有办法遍历枚举的值?

】在Rust中,有没有办法遍历枚举的值?【英文标题】:InRust,isthereawaytoiteratethroughthevaluesofanenum?【发布时间】:2014-02-1717:47:11【问题描述】:我来自Java背景,我可能有类似enumDirectionNORTH,SOUTH,EAST,WEST的东西,我可以使用增强的for... 查看详情

iPhone 有没有办法让用户在其中对应用程序进行评分?

】iPhone有没有办法让用户在其中对应用程序进行评分?【英文标题】:iPhoneisthereawaytoallowausertoratetheappfromwithinit?【发布时间】:2012-03-2315:44:56【问题描述】:我看到一些应用程序带有一个按钮来给应用程序评分。它将他们带到一... 查看详情

js内存泄露

...局变量.未声明变量.使用this创建的变量(this指向window)解决办法:.避免创建全局变量.使用严格模式,在js文件头部或者函数的顶部加上usestrict2.闭包引起的内存泄露原因:闭包可以读取函数内部的变量,然后让这些变量是始终保存... 查看详情

编程范式

...、命令式编程外,还支持以下范式。函数式编程Rust使用闭包(closure)来创建匿名函数:letnum=5;letplus_num=|x:i32|x+num;其中闭包plus_num借用了它作用域中的let绑定num。如果要让闭包获得所有权,可以使用move关键字:letmutnum=5;{letmutad 查看详情

有没有办法使 SQL 变量成为常量?

】有没有办法使SQL变量成为常量?【英文标题】:IsthereawaytomakeaTSQLvariableconstant?【发布时间】:2010-09-0619:12:13【问题描述】:有没有办法让TSQL变量成为常量?【问题讨论】:【参考方案1】:不,但您可以创建一个函数并在其中... 查看详情

有没有办法让 Gulp 在不同的环境中跳过或包含 JavaScript 段?

】有没有办法让Gulp在不同的环境中跳过或包含JavaScript段?【英文标题】:IsthereawaytomakeGulpskiporincludeJavaScriptsegmentsindifferentenvironments?【发布时间】:2022-01-1908:36:31【问题描述】:我正在将一些JavaScript从Jekyll移植到Gulp。在Jekyll中... 查看详情

存储过程返回2个结果数据集-有没有办法只将第一个数据集插入变量但仍然显示第二个?(代码片段)

我有一个运行一系列测试的父存储过程。在此过程中,父级会创建一个“日志”记录,并在实际执行测试之前将其设置为更新。测试是一个存储过程,它根据结果返回“Y”或“N”,并返回返回所有记录的辅助结果集。我希望父... 查看详情

指定 Rust 闭包的生命周期

】指定Rust闭包的生命周期【英文标题】:SpecifyRustclosureslifetime【发布时间】:2020-12-1012:13:03【问题描述】:当我发现这是一个终身问题时,我正在制作执行器/反应器。它与async/Future无关,可以在没有async糖的情况下进行复制。us... 查看详情

Rust 中的闭包生命周期通过简单的模式

】Rust中的闭包生命周期通过简单的模式【英文标题】:ClosurelifetimeinRustthroughsimplepattern【发布时间】:2021-12-1606:36:35【问题描述】:我正在尝试使用2个结构在Rust中重新创建一个简单的回调模式。只要另一个准备好,一个就会传... 查看详情

go的闭包看你犯错,rust却默默帮你排坑

作者|马超责编| 晋兆雨出品 | CSDN博客初识闭包闭包(Closure)在某些编程语言中也被称为Lambda表达式,是能够读取其他函数内部变量的函数。一般只有函数内部的子函数才能读取局部变量,所以闭包这样一个函... 查看详情

rust编程语言入门之函数式语言特性:-迭代器和闭包(代码片段)

函数式语言特性:-迭代器和闭包本章内容闭包(closures)迭代器(iterators)优化改善12章的实例项目讨论闭包和迭代器的运行时性能一、闭包(1)-使用闭包创建抽象行为什么是闭包(closure)闭包:可以捕获其所在环境的匿名函数... 查看详情

有没有办法让列表中变量的变化反映在列表中?

】有没有办法让列表中变量的变化反映在列表中?【英文标题】:Isthereawayforachangeinavariableinalisttobereflectedinthelist?【发布时间】:2020-12-1310:37:23【问题描述】:例如:Variable=1List=[0,Variable,2,3]Variable=5print(List)输出为[0,1,2,3]。除了重... 查看详情

有没有办法使比较运算符成为变量? [复制]

】有没有办法使比较运算符成为变量?[复制]【英文标题】:Isthereawaytomakeacomparisonoperatoravariable?[duplicate]【发布时间】:2012-05-2209:42:27【问题描述】:类似于python:makeavariableequalanoperator(+,/,*,-)我有一些代码,用户可以在其中选择... 查看详情

有没有办法让 C++ 结构值初始化所有 POD 成员变量?

】有没有办法让C++结构值初始化所有POD成员变量?【英文标题】:IsthereawaytomakeaC++structvalue-initializeallPODmembervariables?【发布时间】:2010-10-1407:05:56【问题描述】:假设我有一个同时具有POD和非POD成员变量的C++结构:structStructstd::st... 查看详情