Skip to content

Commit ee3eb40

Browse files
Merge pull request #510 from knight42/patch
给 泛型 那章添加了一道习题
2 parents 6f15fbb + 73a5430 commit ee3eb40

6 files changed

Lines changed: 90 additions & 14 deletions

File tree

action/db/readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ fn main() {
188188
使用了unwrap,解决问题,不过我还是没有学会,函数多值返回时我如何
189189
定义返回值
190190

191-
- 在使用`&conn.query(query,&[]).unwrap()`时,我按照文档操作,文档
192-
说返回的是一个可迭代的数据,那也就是说,我可以使用for循环,将数据打印,
191+
- 在使用`&conn.query(query,&[]).unwrap()`时,我按照文档操作,文档说
192+
返回的是一个可迭代的数据,那也就是说,我可以使用for循环,将数据打印,
193193
但是发现怎么也不能实现:
194194

195195
``` rust
@@ -216,13 +216,13 @@ src/lib.rs:53:37: 53:47 help: run `rustc --explain E0282` to see a detailed expl
216216
error: aborting due to previous error
217217
Could not compile `db`.
218218

219-
``
219+
```
220220
然后去查看了关于postgres模块的所有函数,尝试了无数种办法,依旧没有解决。
221221

222222
可能自己眼高手低,如果从头再把rust的相关教程看一下,可能很早就发现这个问题,
223223
也有可能是因为习惯了写python,导致自己使用固有的思维来看待问题和钻牛角尖,才
224224
导致出现这样的问题,浪费很多的时间。
225225

226226
- 改变思维,把自己当作一个全新的新手,既要利用已有的思想来学习新的语言,同样不要
227-
被自己很精通的语言,固话自己的思维
227+
被自己很精通的语言,固化自己的思维
228228

generic/exercise/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "exercise"
3+
version = "0.1.0"
4+
authors = ["Knight <Knight42@mail.ustc.edu.cn>"]
5+
6+
[dependencies]

generic/exercise/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
README
2+
=======
3+
4+
`cargo run`

generic/exercise/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mod problem1;
2+
3+
fn main() {
4+
problem1::demo("Cargo.toml");
5+
problem1::demo("");
6+
}

generic/exercise/src/problem1.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use std::borrow::Borrow;
2+
use std::fs::File;
3+
use std::io::{BufRead, BufReader};
4+
5+
fn parse<I>(lines: I)
6+
where I: IntoIterator, I::Item: Borrow<str>
7+
{
8+
for line in lines {
9+
println!("{}", line.borrow());
10+
}
11+
}
12+
13+
pub fn demo(path: &str) {
14+
if path.is_empty() {
15+
println!("==== Parsing long string ====");
16+
let content = "some\nlong\ntext";
17+
parse(content.lines());
18+
} else {
19+
println!("==== Parsing text file ====");
20+
let f = File::open(path).unwrap();
21+
let b = BufReader::new(f);
22+
parse(b.lines().map(|l| l.unwrap_or("".to_owned())));
23+
}
24+
}

generic/generic.md

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ fn main() {
7878
}
7979
```
8080

81-
>**输出:**
82-
>101
83-
>200.33
81+
>**输出:**
82+
>101
83+
>200.33
8484
8585
```add<T: Add<T, Output=T>>(a:T, b:T) -> T```就是我们泛型函数,返回值也是泛型T,Add<>中的含义可以暂时忽略,大体意思就是只要参数类型实现了Add trait,就可以被传入到我们的add函数,因为我们的add函数中有相加+操作,所以要求传进来的参数类型必须是可相加的,也就是必须实现了Add trait(具体参考std::ops::Add)。
8686

@@ -119,10 +119,10 @@ fn main() {
119119
println!("{:?}", add(p1, p2));
120120
}
121121
```
122-
>**输出:**
123-
>101
124-
200.33
125-
Point { x: 3, y: 3 }
122+
>**输出:**
123+
>101
124+
200.33
125+
Point { x: 3, y: 3 }
126126

127127
上面的例子稍微更复杂些了,只是我们增加了自定义的类型,然后让add函数依然可以在上面工作。如果对trait不熟悉,请查阅trait相关章节。
128128

@@ -162,13 +162,49 @@ fn main() {
162162
}
163163
```
164164

165-
>**输出:**
166-
>Point { x: 3.2, y: 3.2 }
167-
Point { x: 3, y: 3 }
165+
>**输出:**
166+
>Point { x: 3.2, y: 3.2 }
167+
Point { x: 3, y: 3 }
168168

169169
上面的列子更复杂了些,我们不仅让自定义的Point类型支持了add操作,同时我们也为Point做了泛型化。
170170

171171
```let p1 = Point{x: 1.1f32, y: 1.1f32};```时,Point的T推导为f32类型,这样Point的x和y属性均成了f32类型。因为p1.x+p2.x,所以T类型必须支持Add trait。
172172

173173
### 总结
174174
上面区区几十行的代码,却实现了非泛型语言百行甚至千行代码才能达到的效果,足见泛型的强大。
175+
176+
### 习题
177+
178+
#### 1. Generic lines iterator
179+
180+
##### 问题描述
181+
有时候我们可能做些文本分析工作, 数据可能来源于外部或者程序内置的文本.
182+
请实现一个 `parse` 函数, 只接收一个 lines iterator 为参数, 并输出每行.
183+
要求既能输出内置的文本, 也能输出文件内容.
184+
185+
##### 调用方式及输出参考
186+
```
187+
let lines = "some\nlong\ntext".lines()
188+
parse(do_something_or_nothing(lines))
189+
```
190+
```
191+
some
192+
long
193+
text
194+
```
195+
196+
```
197+
use std::fs:File;
198+
use std::io::prelude::*;
199+
use std::io::BufReader;
200+
let lines = BufReader::new(File::open("/etc/hosts").unwrap()).lines()
201+
parse(do_some_other_thing_or_nothing(lines))
202+
```
203+
```
204+
127.0.0.1 localhost.localdomain localhost
205+
::1 localhost.localdomain localhost
206+
...
207+
```
208+
209+
##### Hint
210+
本书`类型系统中的几个常见 trait`章节中介绍的 AsRef, Borrow 等 trait 应该能派上用场.

0 commit comments

Comments
 (0)