- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要一个闭包来引用其封闭环境中的对象的各个部分。该对象在环境中创建并限定在它的范围内,但一旦创建它就可以安全地移动到闭包中。
用例是一个函数,它执行一些准备工作并返回一个将完成其余工作的闭包。这种设计的原因是执行约束:工作的第一部分涉及分配,其余部分不得分配。这是一个最小的例子:
fn stage_action() -> Box<Fn() -> ()> {
// split a freshly allocated string into pieces
let string = String::from("a:b:c");
let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];
// the returned closure refers to the subtrings vector of
// slices without any further allocation or modification
Box::new(move || {
for sub in substrings.iter() {
println!("{}", sub);
}
})
}
fn main() {
let action = stage_action();
// ...executed some time later:
action();
}
编译失败,正确说明 &string[0..1]
和其他的不能比 string
长。但是如果 string
被移动到闭包中,就不会有问题。有没有一种方法可以强制这种情况发生,或者有另一种方法可以让闭包引用在闭包之外创建的对象的各个部分?
我还尝试创建一个具有相同功能的struct
来使移动完全明确,但是doesn't compile either .同样,编译失败,错误是 &later[0..1]
和其他人只活到函数结束,但“借用的值必须在静态生命周期内有效”。
甚至completely avoiding a Box
似乎没有帮助 - 编译器提示该对象的生命周期不够长。
最佳答案
这里没有什么特定于闭包的;它相当于:
fn main() {
let string = String::from("a:b:c");
let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];
let string = string;
}
您正试图在有未完成的借用时移动 String
。在我这里的例子中,它是另一个变量;在你的例子中它是闭包的环境。无论哪种方式,您仍在移动它。
此外,您正在尝试将子字符串移动到与拥有字符串相同的闭包环境中。这使得整个问题等同于 Why can't I store a value and a reference to that value in the same struct? :
struct Environment<'a> {
string: String,
substrings: Vec<&'a str>,
}
fn thing<'a>() -> Environment<'a> {
let string = String::from("a:b:c");
let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];
Environment {
string: string,
substrings: substrings,
}
}
The object is created within the environment and is scoped to it
我不同意; string
和 substrings
在闭包环境的外部 创建并移入其中。正是这个举动让你绊倒了。
once created it could be safely moved to the closure.
在这种情况下是正确的,但这只是因为您,程序员,可以保证在 String
中的字符串数据的地址将保持不变。您知道这一点有两个原因:
String
在内部通过堆分配实现,因此移动 String
不会移动字符串数据。String
永远不会发生突变,这可能会导致字符串重新分配,从而使任何引用无效。对于您的示例,最简单 解决方案是简单地将切片转换为 String
并让闭包完全拥有它们。如果这意味着您可以释放一个大字符串以支持几个较小的字符串,这甚至可能是一个净 yield 。
否则,您符合 Why can't I store a value and a reference to that value in the same struct? 中“生命周期跟踪过度的特殊情况”下列出的标准。 , 所以你可以使用像这样的 crate :
use owning_ref::RcRef; // 0.4.1
use std::rc::Rc;
fn stage_action() -> impl Fn() {
let string = RcRef::new(Rc::new(String::from("a:b:c")));
let substrings = vec![
string.clone().map(|s| &s[0..1]),
string.clone().map(|s| &s[2..3]),
string.clone().map(|s| &s[4..5]),
];
move || {
for sub in &substrings {
println!("{}", &**sub);
}
}
}
fn main() {
let action = stage_action();
action();
}
use ouroboros::self_referencing; // 0.2.3
fn stage_action() -> impl Fn() {
#[self_referencing]
struct Thing {
string: String,
#[borrows(string)]
substrings: Vec<&'this str>,
}
let thing = ThingBuilder {
string: String::from("a:b:c"),
substrings_builder: |s| vec![&s[0..1], &s[2..3], &s[4..5]],
}
.build();
move || {
thing.with_substrings(|substrings| {
for sub in substrings {
println!("{}", sub);
}
})
}
}
fn main() {
let action = stage_action();
action();
}
请注意,我不是这两个 crate 的专家用户,因此这些示例可能不是它们的最佳用途。
关于rust - 闭包中引用的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42747620/
我在一个简单的 GTK 应用程序中有两个小部件: extern crate gdk; extern crate gtk; use super::desktop_entry::DesktopEntry;
我想做这样的事情: const vegetableColors = {corn: 'yellow', peas: 'green'}; const {*} = vegetableColors; cons
该属性它存储在 gradle 中的什么位置? subprojects { println it.class.name // DefaultProject_Decorated depen
我想在 jQuery 闭包中看到窗口属性“otherName”描述符。但 进入 jQuery 闭包 'otherName' 描述符显示未定义,我认为可能 是 getOwnPropertyDescrip
我曾经看过 Douglas Crockford 的一次演讲,在 javascript 的上下文中,他提到将 secret 存储在闭包中可能很有用。 我想这可以在 Java 中像这样天真地实现: pub
我很难理解 Swift 中闭包中真正发生的事情,希望有人能帮助我理解。 class MyClass { func printWhatever(words: String) {
我有两个 3 表:用户、个人资料、friend_request $my_profile_id变量存储用户个人资料ID的值 $my_user_id = Auth::user()->id; $my_pro
我正在尝试通过使用 GLFW 的包装来学习 Swift GLFW 允许添加错误回调: GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cb
我是一名优秀的程序员,十分优秀!