在实现 LazyList 的一个版本(一个不可变的延迟计算的记忆单链表,就像 Haskell 列表)时,我遇到了一个实现问题,IntoIterator因为代码在我认为应该删除引用时却没有删除。以下代码已被简化,只是为了显示问题;因此,它不是通用的,也不包括与实现无关的所有方法IntoIterator:
use std::cell::UnsafeCell;
use std::mem::replace;
use std::rc::Rc;
// only necessary because Box<FnOnce() -> R> doesn't yet work...
trait Invoke<R = ()> {
fn invoke(self: Box<Self>) -> R;
}
impl<'a, R, F: 'a + FnOnce() -> R> Invoke<R> for F {
#[inline(always)]
fn invoke(self: Box<F>) -> R {
(*self)()
}
}
// not thread safe
struct Lazy<'a, T: 'a>(UnsafeCell<LazyState<'a, T>>);
enum LazyState<'a, T: 'a> {
Unevaluated(Box<Invoke<T> + 'a>),
EvaluationInProgress,
Evaluated(T),
}
use self::LazyState::*; …Run Code Online (Sandbox Code Playgroud) fn count_spaces(text: Vec<u8>) -> usize {
text.split(|c| c == 32u8).count()
}
Run Code Online (Sandbox Code Playgroud)
上面的函数无法编译,并在比较时给出以下错误:
特征 `&u8: std::cmp::PartialEq` 不满足
我将其读为:“c是借用的字节,无法与常规字节进行比较”,但我一定读错了。
根据特定值拆分 a 的适当方法是什么Vec<u8>?
我确实意识到在读取文件时有一些选项,比如分割 aBufReader或者我可以将向量转换为字符串并使用str::split. 我可能会采用这样的解决方案(传递 aBufReader而不是 a Vec<u8>),但现在我只是在玩,测试东西并想知道我做错了什么。
为什么这段代码会编译?
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let x = "eee";
let &m;
{
let y = "tttt";
m = longest(&x, &y);
}
println!("ahahah: {}", m);
}
Run Code Online (Sandbox Code Playgroud)
对我来说,由于生命周期,应该存在编译错误。如果我用 编写相同的代码i64,则会出现错误。
fn ooo<'a>(x: &'a i64, y: &'a i64) -> &'a i64 {
if x > y {
x
} else {
y
}
}
fn main() {
let x = …Run Code Online (Sandbox Code Playgroud) struct Test {
a: i32,
b: i32,
}
fn other(x: &mut i32, _refs: &Vec<&i32>) {
*x += 1;
}
fn main() {
let mut xes: Vec<Test> = vec![Test { a: 3, b: 5 }];
let mut refs: Vec<&i32> = Vec::new();
for y in &xes {
refs.push(&y.a);
}
xes.iter_mut().for_each(|val| other(&mut val.b, &refs));
}
Run Code Online (Sandbox Code Playgroud)
虽然refs仅保存对a元素的 -member 的引用xes并且函数other使用b-member,但 rust 会产生以下错误:
error[E0502]: cannot borrow `xes` as mutable because it is also borrowed as immutable …Run Code Online (Sandbox Code Playgroud) 我正在学习Rust,我正在与借阅检查员作斗争.
我有一个基本的Point结构.我有一个scale修改点的所有坐标的函数.我想从另一个名为的方法调用此方法convert:
struct AngleUnit;
struct Point {
x: f32,
y: f32,
z: f32,
unit: AngleUnit,
}
fn factor(_from: AngleUnit, _to: AngleUnit) -> f32 {
1.0
}
impl Point {
pub fn new(x: f32, y: f32, z: f32, unit: AngleUnit) -> Point {
Point { x, y, z, unit }
}
fn scale(&mut self, factor: f32) {
self.x *= factor;
self.y *= factor;
self.z *= factor;
}
fn convert(&mut self, unit: AngleUnit) {
let point_unit …Run Code Online (Sandbox Code Playgroud) 我正试图通过Rust by Example网站传递"Tuple课程" ,但我仍然坚持格式化的输出实现.我有这个代码,它打印传递的矩阵:
#[derive(Debug)]
struct Matrix{
data: Vec<Vec<f64>> // [[...], [...],]
}
impl fmt::Display for Matrix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let output_data = self.data
// [[1, 2], [2, 3]] -> ["1, 2", "2, 3"]
.into_iter()
.map(|row| {
row.into_iter()
.map(|value| value.to_string())
.collect::<Vec<String>>()
.join(", ")
})
.collect::<Vec<String>>()
// ["1, 2", "2, 3"] -> ["(1, 2)", "(2, 3)"]
.into_iter()
.map(|string_row| { format!("({})", string_row) })
// ["(1, 2)", "(2, 3)"] -> "(1, 2),\n(2, 3)"
.collect::<Vec<String>>()
.join(",\n"); …Run Code Online (Sandbox Code Playgroud) 我有一个借用的功能,HashMap我需要通过键访问值.为什么通过引用而不是值来获取键和值?
我的简化代码:
fn print_found_so(ids: &Vec<i32>, file_ids: &HashMap<u16, String>) {
for pos in ids {
let whatever: u16 = *pos as u16;
let last_string: &String = file_ids.get(&whatever).unwrap();
println!("found: {:?}", last_string);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我必须指定密钥作为参考,即file_ids.get(&whatever).unwrap()代替file_ids.get(whatever).unwrap()?
据我所知,它last_string必须是类型&String,意思是借用的字符串,因为拥有的集合是借用的.是对的吗?
与上述点类似,我假设pos是类型是正确的,&u16因为它需要借来的值ids?
我想使用HashSet快速字符串查找,但我似乎无法找到一种方法来传递字符串变量contains没有编译器错误.
refs = HashSet::new();
let first_pass = link_regex.replace_all(&buffer, |caps: &Captures| {
if caps.len() == 2 {
refs.insert(caps.at(2).unwrap());
}
caps.at(1).unwrap().to_owned()
});
let out = ref_regex.replace_all(&first_pass, |caps: &Captures| {
let capture = caps.at(1).unwrap().to_owned();
// only remove if we've seen it before
if refs.contains(capture) {
return "".to_string();
}
capture
});
Run Code Online (Sandbox Code Playgroud)
这会导致此错误:
src/bin/remove_links.rs:30:26: 30:33 error: mismatched types [E0308]
src/bin/remove_links.rs:30 if refs.contains(capture) {
^~~~~~~
src/bin/remove_links.rs:30:26: 30:33 help: run `rustc --explain E0308` to see a detailed explanation
src/bin/remove_links.rs:30:26: 30:33 note: expected type …Run Code Online (Sandbox Code Playgroud) 从Rust书中关于所有权的章节,可以通过转移所有权或使用可变或不可变引用将不可复制的值传递给函数.当您转移值的所有权时,它不能再用于原始函数:如果您愿意,必须将其返回.传递引用时,您可以借用该值并仍然可以使用它.
我来自默认值不可变的语言(Haskell,Idris等).因此,我可能永远不会考虑使用引用.在两个地方拥有相同的价值对我来说是危险的(或者至少是尴尬的).由于引用是一个功能,因此必须有理由使用它们.
有没有情况我应该强迫自己使用参考?这些情况是什么?为什么它们有益?或者他们只是为了方便和默认通过所有权是好的?
我正在尝试Rust并且在理解"借用"方面存在问题.
struct Foo<T> {
data: T,
}
impl<T> Foo<T> {
fn new(data: T) -> Self {
Foo {
data: data,
}
}
}
fn main() {
let mut foo = Foo::new("hello");
let x = &mut foo;
let y = &mut foo;
println!("{}", foo.data);
}
Run Code Online (Sandbox Code Playgroud)
为什么这段代码编译没有错误?毕竟,我得到了多个可变引用foo.以下内容写入文档:
参考规则
让我们回顾一下我们讨论的关于参考文献的内容:
a)在任何给定时间,您可以拥有(但不是两个)一个可变引用或任意数量的不可变引用.
b)参考文献必须始终有效.
这种行为的原因是什么?谢谢!