Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions action/db/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ fn main() {
使用了unwrap,解决问题,不过我还是没有学会,函数多值返回时我如何
定义返回值

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

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

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

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

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

6 changes: 6 additions & 0 deletions generic/exercise/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "exercise"
version = "0.1.0"
authors = ["Knight <Knight42@mail.ustc.edu.cn>"]

[dependencies]
4 changes: 4 additions & 0 deletions generic/exercise/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
README
=======

`cargo run`
6 changes: 6 additions & 0 deletions generic/exercise/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod problem1;

fn main() {
problem1::demo("Cargo.toml");
problem1::demo("");
}
24 changes: 24 additions & 0 deletions generic/exercise/src/problem1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::borrow::Borrow;
use std::fs::File;
use std::io::{BufRead, BufReader};

fn parse<I>(lines: I)
where I: IntoIterator, I::Item: Borrow<str>
{
for line in lines {
println!("{}", line.borrow());
}
}

pub fn demo(path: &str) {
if path.is_empty() {
println!("==== Parsing long string ====");
let content = "some\nlong\ntext";
parse(content.lines());
} else {
println!("==== Parsing text file ====");
let f = File::open(path).unwrap();
let b = BufReader::new(f);
parse(b.lines().map(|l| l.unwrap_or("".to_owned())));
}
}
56 changes: 46 additions & 10 deletions generic/generic.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ fn main() {
}
```

>**输出:**
>101
>200.33
>**输出:**
>101
>200.33

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

Expand Down Expand Up @@ -119,10 +119,10 @@ fn main() {
println!("{:?}", add(p1, p2));
}
```
>**输出:**
>101
200.33
Point { x: 3, y: 3 }
>**输出:**
>101
200.33
Point { x: 3, y: 3 }

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

Expand Down Expand Up @@ -162,13 +162,49 @@ fn main() {
}
```

>**输出:**
>Point { x: 3.2, y: 3.2 }
Point { x: 3, y: 3 }
>**输出:**
>Point { x: 3.2, y: 3.2 }
Point { x: 3, y: 3 }

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

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

### 总结
上面区区几十行的代码,却实现了非泛型语言百行甚至千行代码才能达到的效果,足见泛型的强大。

### 习题

#### 1. Generic lines iterator

##### 问题描述
有时候我们可能做些文本分析工作, 数据可能来源于外部或者程序内置的文本.
请实现一个 `parse` 函数, 只接收一个 lines iterator 为参数, 并输出每行.
要求既能输出内置的文本, 也能输出文件内容.

##### 调用方式及输出参考
```
let lines = "some\nlong\ntext".lines()
parse(do_something_or_nothing(lines))
```
```
some
long
text
```

```
use std::fs:File;
use std::io::prelude::*;
use std::io::BufReader;
let lines = BufReader::new(File::open("/etc/hosts").unwrap()).lines()
parse(do_some_other_thing_or_nothing(lines))
```
```
127.0.0.1 localhost.localdomain localhost
::1 localhost.localdomain localhost
...
```

##### Hint
本书`类型系统中的几个常见 trait`章节中介绍的 AsRef, Borrow 等 trait 应该能派上用场.