我有一个以常量形式定义的数组,在任何函数之外:
const VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")];
我尝试使用位于Iterator
上的find()
方法,以便根据谓词从数组中提取单个元素:
VALUES.iter().find(|&&(name, _)| name == 'A');
在这种形式下,它工作正常。但是,我无法将找到的元素评估为任何内容,因为我尝试创建let
绑定时,尝试绑定结果,根据文档应该返回{{1} }。
让我们将第二行更改为不起作用的行:
Option<T>
根据文档,人们会期望这会返回const VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")];
fn main() {
let result = VALUES.iter().find(|&&(name, _)| name == 'A');
}
,但我会收到编译错误:
Option<T>
我完全糊涂了;我确定我已经搞砸了#34;借用检查器&#34;。也许有人可以指出我正确的方向?
答案 0 :(得分:2)
问题在于您将该数组转换为迭代器的具体方式。
首先,Rust中的const
实际上并不存在于任何地方。相反,他们会在他们使用的任何地方替换价值。因此,每次使用常量时,您都会获得它的新副本。
其次,您正在使用IntoIterator::into_iter
。这将主题按值并将其转换为迭代器。
这些与第三部分结合:IntoIterator
是针对固定大小的数组实现的。它仅针对指针实现为固定大小的数组。因此,为了调用into_iter
,编译器必须插入一个自动借用的调用者。
那么,实际发生的是:
let t = {
// Make a new copy of `VALUES`.
let values: [(char, &str); 5] = VALUES;
// Borrow it.
let values: &[_] = &values;
// Call `into_iter` on the borrow.
IntoIterator::into_iter(values).find(|&&(name, _)| name == 'A')
};
这会导致问题,因为编译器必须同时复制和借用VALUES
才能获得迭代器。像所有临时工一样,复制品只能在声明中存在,但借用(通过绑定变量)必须比这更长寿。
最好的解决方案是将VALUES
指针添加到数组中。这可以防止复制整个阵列;相反,你只在每次使用时复制指针。
const VALUES: &[(char, &str)] = &[...];
或者,您可以明确制作VALUES
的副本并将其存储在变量中,然后在上使用into_iter
。但是,和以前一样,这会引入不必要的复制。
答案 1 :(得分:0)
DK.'s answer是正确的,但我建议您进行更简单的更改以使代码正常工作 - 使用static
代替const
。
来自documentation about static and const:
更具体地说,Rust中的常量在内存中没有固定的地址。
静态项目在使用时不会内联。这意味着每个值只有一个实例,它位于内存中的固定位置。
切换到static
可以获得正在迭代的内容的内存地址。
static VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")];
fn main() {
let result = VALUES.iter().find(|&&(name, _)| name == 'A');
}
此处result
为Option<&(char, &str)>
。