Skip to content

Commit

Permalink
done rustlings summary
Browse files Browse the repository at this point in the history
  • Loading branch information
MoonOld committed Apr 7, 2023
1 parent e8dcac2 commit a7e2209
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 4 deletions.
2 changes: 2 additions & 0 deletions content/about/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ date: 2023-03-07T18:26:02.18+0800
description: 一篇自我介绍
featuredImage: inWinter.jpg
featuredImagePreview: laptop.jpg
hiddenFromHomePage: true
hiddenFromSearch: false
toc:
auto: false
lightgallery: true
Expand Down
6 changes: 3 additions & 3 deletions content/posts/cpu/BranchPrediction.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ tags:
- 虚函数
categories:
- 计算机原理
featuredImage: /images/featuredImage.jpg
featuredImage: /images/branch.jpg
resources:
- name: featured-image
src: /images/featuredImage.jpg
src: /images/branch.jpg
- name: featured-image-preview
src: /images/featuredImage.jpg
src: /images/branch.jpg
toc: true
lightgallery: true

Expand Down
1 change: 0 additions & 1 deletion content/posts/lab/rcore/record.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ draft: false
description: 记录一下自己的留级rcore
keywords:
comment: false
weight: 0
tags:
- rust
- os
Expand Down
134 changes: 134 additions & 0 deletions content/posts/lab/rcore/rustlings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
title: Rustlings疑难记录
subtitle: 将做Rustlings过程中觉得疑惑或者有趣的地方单独列出来
date: 2023-04-07T14:03:22+08:00
draft: false
description: 将做Rustlings过程中觉得疑惑或者有趣的地方单独列出来
keywords:
comment: false
tags:
- Rust
categories:
- Lab
toc: true
lightgallery: true
# See details front matter: https://fixit.lruihao.cn/documentation/content/#front-matter
---




## Ownership
```./exercises/vecs/vecs1.rs```
``` rust
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = Vec::from(a);// TODO: declare your vector here with the macro for vectors

(a, v)
}
```
代码这里的第三行很明显是将a的所有权转移进了from函数中,但是结尾却可以返回为一个元组,按道理来说a在这已经没有生命周期了才对。查看rust源码如下
``` rust
fn from(s: [T; N]) -> Vec<T> {
<[T]>::into_vec(
#[rustc_box]
Box::new(s),
)
}
```
也就是调用了数组类型的into_vec方法。这里使用了i32类型,那么调用的就是i32的into_vec方法。到这一步我突然就有点明白为什么这个数组和vec可以共存了。与Java不同,数组本身可能不是一种完全的类型,只要数组元素类型T实现了Copy特征,传递进from的就是Copy的数组。为了验证这个想法,我写了下面这个验证函数。
``` rust
fn array_and_vec() -> ([String; 4], Vec<String>) {
let a = ["abc".to_string(), "sd".to_string(), "sdf".to_string(), "df".to_string()]; // a plain array
let v = Vec::from(a);// TODO: declare your vector here with the macro for vectors

(a, v)
}
```
果不其然,报错如下
``` text
error[E0382]: use of moved value: `a`
--> exercises/vecs/vecs1.rs:12:6
|
9 | let a = ["abc".to_string(), "sd".to_string(), "sdf".to_string(), "df".to_string()]; // a plain array
| - move occurs because `a` has type `[String; 4]`, which does not implement the `Copy` trait
10 | let v = Vec::from(a);// TODO: declare your vector here with the macro for vectors
| - value moved here
11 |
12 | (a, v)
| ^ value used here after move
```
但是实际上并不如此。`array`类型只是自动实现了类型允许的特征。见[array文档](https://doc.rust-lang.org/std/primitive.array.html),摘抄如下
> Arrays of any size implement the following traits if the *element type* allows it:
> * Copy
> * Clone
> * Debug
> * IntoIterator (implemented for [T; N], &[T; N] and &mut [T; N])
> * PartialEq, PartialOrd, Eq, Ord
> * Hash
> * AsRef, AsMut
> * Borrow, BorrowMut
这里以`Copy`特征为例子探讨一下Rust的源码
``` rust
#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
impl<T: Copy, const N: usize> Copy for [T; N] {}
```
空的函数体表示直接通过位复制。也就是直接把array原封不动复制过去。在[Copy文档](https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone)中,解释了Copy只能是bit-wise copy且不可重载。所以没办法实现类似clone的copy去防止转移所有权了。

回到最开始的问题,答案一目了然了,这里传递的数组变量并没有转移所有权,因为数组类型自动实现了i32所实现的Copy特征。

## Cow(Copy on Write)
Cow是一个智能指针类型,实现了Copy on write。下面这段代码位于```./exercises/standard_library_types/cow1.rs```
``` rust
// No clone occurs because `input` is already owned.
let slice = vec![-1, 0, 1];
let mut input = Cow::from(slice);
match abs_all(&mut input) {
// TODO
Cow::Owned(_) => println!("I own this slice!"),
_ => panic!("expected borrowed value"),
}
```
这个问题是源于注释中 ***No clone occurs*** 这一点似乎和Copy on write的理念不符。就类似上面所有权的问题了,因为```Cow```类型的```From<Vec<T>>```方法实现如下
``` rust
fn from(v: Vec<T>) -> Cow<'a, [T]> {
Cow::Owned(v)
}
```
因为接受的就是所有权的转移,所以```from```方法创建新值的时候直接使用了```Owned```的包装。因此```abs_all```处理负数的逻辑实际上是在```Owned```上进行的操作,自然没有发生clone。

## Macros
1. 宏需要使用```#[macro_export]```宏来进行宏的暴露,可以使其全局可见。
``` rust
mod macros {
#[macro_export]
macro_rules! my_macro {
() => {
println!("Check out my macro!");
};
}
}
fn main() {
my_macro!();
}
```
> Macros labeled with #[macro_export] are always pub and can be referred to by other crates, either by path or by #[macro_use] as described above.
也就是说,可以直接通过```crate::path::macro!()```去使用,或者使用```#[macro_use]```去import macros。

2. 宏的匹配语句必须要以```;```分号结尾。
``` rust
macro_rules! my_macro {
() => {
println!("Check out my macro!");
}; // this semicolon matters
( $val:expr) => {
println!("Look at this other macro: {}", $val);
}; // this semicolon matters
}
```
按照[decl-marcos](https://veykril.github.io/tlborm/decl-macros/macros-methodical.html#macro_rules)解释, ***As noted previously, macro_rules! is itself a syntax extension, meaning it is technically not part of the Rust syntax. It uses the following forms*** 也就是必须要在每个匹配的rule后加分号,这是```macro_rules!```自己的规则,与rust语法中模式匹配是不兼容的。具体语法参见[Macros By Example](https://doc.rust-lang.org/reference/macros-by-example.html)

最后想说一句,Rustlings提供了from和into的traits实现题目,这实在是太聪明的决定了。能够独立完成这两个题目,就已经是具备了初步编码rust的能力了。
<!--more-->
File renamed without changes

0 comments on commit a7e2209

Please sign in to comment.