Appearance
智能指针1: exercises/smart_pointers/box1.rs
题目
rust
// box1.rs
//
// At compile time, Rust needs to know how much space a type takes up. This
// becomes problematic for recursive types, where a value can have as part of
// itself another value of the same type. To get around the issue, we can use a
// `Box` - a smart pointer used to store data on the heap, which also allows us
// to wrap a recursive type.
//
// The recursive type we're implementing in this exercise is the `cons list` - a
// data structure frequently found in functional programming languages. Each
// item in a cons list contains two elements: the value of the current item and
// the next item. The last item is a value called `Nil`.
//
// Step 1: use a `Box` in the enum definition to make the code compile
// Step 2: create both empty and non-empty cons lists by replacing `todo!()`
//
// Note: the tests should not be changed
//
// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
#[derive(PartialEq, Debug)]
pub enum List {
Cons(i32, List),
Nil,
}
fn main() {
println!("This is an empty cons list: {:?}", create_empty_list());
println!(
"This is a non-empty cons list: {:?}",
create_non_empty_list()
);
}
pub fn create_empty_list() -> List {
todo!()
}
pub fn create_non_empty_list() -> List {
todo!()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_empty_list() {
assert_eq!(List::Nil, create_empty_list())
}
#[test]
fn test_create_non_empty_list() {
assert_ne!(create_empty_list(), create_non_empty_list())
}
}
在编译时,Rust 需要知道每个类型占用了多少空间。 这对于递归类型来说是有问题的,因为一个值可以具有相同类型的另一个值作为其自身的一部分。 为了解决这个问题,我们可以使用Box
——一个用于在堆上存储数据的智能指针,它还允许我们包装递归类型。
我们在本练习中实现的递归类型是 cons list
- 函数式编程语言中常见的一种数据结构。 cons 列表中的每个项目都包含两个元素:当前项目的值和下一个项目的值。 最后一项是一个名为Nil
的值。
- 第1步:在枚举定义中使用
Box
来使代码编译 - 第2步:通过替换
todo!()
创建空和非空 cons 列表
注意:不能修改单元测试代码。
题目解析
编译器提示的信息如下:
txt
⚠️ Compiling of exercises/smart_pointers/box1.rs failed! Please try again. Here's the output:
error[E0072]: recursive type `List` has infinite size
--> exercises/smart_pointers/box1.rs:24:1
|
24 | pub enum List {
| ^^^^^^^^^^^^^
25 | Cons(i32, List),
| ---- recursive without indirection
|
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
25 | Cons(i32, Box<List>),
| ++++ +
error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.
编译器提示我们:
- 递归类型
List
具有无限大小 - 并提示我们可以添加智能指针,来打破循环,并且在代码上提示我们可以标注
Box<List>
。
List
大小不固定,意味着我们不知道该分配多少的空间来存储它,因此我们可以使用智能指针将其包裹起来。创建空的列表很简单,我们直接返回List::Nil
就可以了,对于非空列表,我们只需要按照Cons
的定义来创建即可。
rust
#[derive(PartialEq, Debug)]
pub enum List {
Cons(i32, List),
Cons(i32, Box<List>),
Nil,
}
fn main() {
println!("This is an empty cons list: {:?}", create_empty_list());
println!(
"This is a non-empty cons list: {:?}",
create_non_empty_list()
);
}
pub fn create_empty_list() -> List {
todo!()
List::Nil
}
pub fn create_non_empty_list() -> List {
todo!()
List::Cons(10, Box::new(List::Nil))
}