这个Python代码最接近的等效Rust代码是什么?
a, b = 1, 2
a, b = b, a + b
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个迭代的Fibonacci函数.我有Python代码我想转换为Rust.一切都很好,除了交换部分.
def fibonacci(n):
if n < 2:
return n
fibPrev = 1
fib = 1
for num in range(2, n):
fibPrev, fib = fib, fib + fibPrev
return fib
Run Code Online (Sandbox Code Playgroud) 我正在编写一个链表来包围Rust的生命周期,所有权和引用.我有以下代码:
pub struct LinkedList {
head: Option<Box<LinkedListNode>>,
}
pub struct LinkedListNode {
next: Option<Box<LinkedListNode>>,
}
impl LinkedList {
pub fn new() -> LinkedList {
LinkedList { head: None }
}
pub fn prepend_value(&mut self) {
let mut new_node = LinkedListNode { next: None };
match self.head {
Some(ref head) => new_node.next = Some(*head),
None => new_node.next = None,
};
self.head = Some(Box::new(new_node));
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
但是我收到以下编译错误:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:18:52
|
18 | …Run Code Online (Sandbox Code Playgroud) 我想在不使用任何克隆的情况下将旧变体的字段移动到新变体时更新枚举变体:
enum X {
X1(String),
X2(String),
}
fn increment_x(x: &mut X) {
*x = match *x {
X::X1(s) => X::X2(s),
X::X2(s) => X::X1(s),
}
}
Run Code Online (Sandbox Code Playgroud)
这并不工作,因为我们不能移动s的&mut X.
请不要建议实现enum X { X1, X2 }和使用struct S { variant: X, str: String }等等.这是一个简化的例子,想象在变体中有许多其他字段,并希望将一个字段从一个变量移动到另一个变体.
我正在编写以下格式的函数:
fn pop(data: &mut Vec<Option<T>>) -> Option<T> {
// Let the item be the current element at head
let item = data[0];
// and "remove" it.
data[0] = None;
item
}
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做时,我得到一个"无法移出索引内容"错误,这是有道理的.当我试图改变它,从而item是一个参考,我得到一个错误,当我尝试设置data[0]到None,这也是情理之中.
有什么方法可以做我想做的事吗?在我看来,无论我是否想要返回引用,我都必须从Vec中获取该元素的所有权.
我注意到Vec有一个swap_remove方法,它几乎完全符合我的要求,除了它与Vec中已有的元素交换,而不是我想要的任意值.我知道我可以附加None到Vec的末尾并使用swap_remove,但我有兴趣看看是否还有另一种方法.
有时我会遇到一个问题,由于实现细节应该对用户不可见,我需要“销毁” a&mut并在内存中替换它。这通常最终发生在递归方法或递归结构的 IntoIterator 实现中。它通常遵循以下形式:
fn create_something(self);
pub fn do_something(&mut self) {
// What you want to do
*self = self.create_something();
}
Run Code Online (Sandbox Code Playgroud)
我在当前项目中碰巧遇到的一个例子是在我编写的 KD 树中,当我“删除”一个节点时,我没有执行逻辑来重新排列子节点,而是解构我需要删除并重建它的节点从其子树中的值:
// Some recursive checks to identify is this is our node above this
if let Node{point, left, right} = mem::replace(self, Sentinel) {
let points = left.into_iter().chain(right.into_iter()).collect();
(*self) = KDNode::new(points);
Some(point)
} else {
None
}
Run Code Online (Sandbox Code Playgroud)
另一个更深入的例子是这个 KDTree 的 IntoIterator,它必须将一个curr值移出迭代器,测试它,然后替换它:
// temporarily swap self.curr with a dummy value so we can
// move …Run Code Online (Sandbox Code Playgroud) 参数可以传递给函数并修改:
fn set_42(int: &mut i32) {
*int += 42;
}
fn main() {
let mut int = 0;
set_42(&mut int);
println!("{:?}", int);
}
Run Code Online (Sandbox Code Playgroud)
输出:
42
Run Code Online (Sandbox Code Playgroud)
天真地改变代码以使用切片失败了一大堆错误:
fn pop_front(slice: &mut [i32]) {
*slice = &{slice}[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Run Code Online (Sandbox Code Playgroud)
输出:
<anon>:2:14: 2:27 error: mismatched types:
expected `[i32]`,
found `&[i32]`
(expected slice,
found &-ptr) [E0308]
<anon>:2 *slice = &{slice}[1..];
^~~~~~~~~~~~~
<anon>:2:14: 2:27 help: see the detailed explanation …Run Code Online (Sandbox Code Playgroud) 我有以下内容:
enum SomeType {
VariantA(String),
VariantB(String, i32),
}
fn transform(x: SomeType) -> SomeType {
// very complicated transformation, reusing parts of x in order to produce result:
match x {
SomeType::VariantA(s) => SomeType::VariantB(s, 0),
SomeType::VariantB(s, i) => SomeType::VariantB(s, 2 * i),
}
}
fn main() {
let mut data = vec![
SomeType::VariantA("hello".to_string()),
SomeType::VariantA("bye".to_string()),
SomeType::VariantB("asdf".to_string(), 34),
];
}
Run Code Online (Sandbox Code Playgroud)
我现在想调用transform每个元素data并将结果值存回data.现在,我当然可以做类似的事情,data.into_iter().map(transform).collect()但这将分配一个新的Vec.有没有办法在就地执行此操作,重用已分配的内存data?有一次Vec::map_in_place在Rust,但它已被删除了一段时间(我认为在1.4左右).
作为解决方法,我目前添加Dummy-variant SomeType,然后执行以下操作:
for x in …Run Code Online (Sandbox Code Playgroud) 我想收集结构的更改并立即应用它们.基本大纲如下所示:
enum SomeEnum {
Foo,
Bar,
}
struct SomeStruct {
attrib: SomeEnum,
next_attrib: Option<SomeEnum>,
}
impl SomeStruct {
pub fn apply_changes(&mut self) {
if let Some(se) = self.next_attrib {
self.attrib = se;
}
self.next_attrib = None;
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下编译器错误:
Run Code Online (Sandbox Code Playgroud)error[E0507]: cannot move out of borrowed content --> src/lib.rs:13:27 | 13 | if let Some(se) = self.next_attrib { | -- ^^^^ cannot move out of borrowed content | | | hint: to prevent move, use `ref se` or `ref mut se` …
我有一个第三方库的函数,需要变量的所有权。不幸的是这个变量在Rc<RefCell<Option<Foo>>>.
我的代码看起来像这样简化:
use std::cell::RefCell;
use std::rc::Rc;
pub struct Foo {
val: i32,
}
fn main() {
let foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));
if let Some(f) = foo.into_inner() {
consume_foo(f);
}
}
fn consume_foo(f: Foo) {
println!("Foo {} consumed", f.val)
}
Run Code Online (Sandbox Code Playgroud)
use std::cell::RefCell;
use std::rc::Rc;
pub struct Foo {
val: i32,
}
fn main() {
let foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));
if let Some(f) = foo.into_inner() {
consume_foo(f);
}
}
fn consume_foo(f: Foo) …Run Code Online (Sandbox Code Playgroud) 我偶然发现了以下场景:
fn compute_values(value: &mut String) {
// the first computation should always work:
let computed_value = String::from("computed value");
// override the default String with the computed value:
*value = computed_value;
// some more code that returns a Result with values or an error message
}
fn main() {
let mut value = String::from("default value");
compute_values(&mut value);
println!("value: {value}")
}
Run Code Online (Sandbox Code Playgroud)
这段代码按照我的预期使用 my 进行编译rustc 1.74.1 (a28077b28 2023-12-04)并输出value: computed value,但问题是,该代码是否泄漏内存。
据我了解,*value = computed_value;进入并且它不再可用(rust编译器确认了这一点,我之后不能computed_value。)并且在函数作用域结束时不会取消分配。由于这一行有效地将 a 分配给 …