diff --git a/action/db/readme.md b/action/db/readme.md index 15cb0e6..b38233e 100644 --- a/action/db/readme.md +++ b/action/db/readme.md @@ -188,8 +188,8 @@ fn main() { 使用了unwrap,解决问题,不过我还是没有学会,函数多值返回时我如何 定义返回值 -- 在使用`&conn.query(query,&[]).unwrap()`时,我按照文档操作,文档 -说返回的是一个可迭代的数据,那也就是说,我可以使用for循环,将数据打印, +- 在使用`&conn.query(query,&[]).unwrap()`时,我按照文档操作,文档说 +返回的是一个可迭代的数据,那也就是说,我可以使用for循环,将数据打印, 但是发现怎么也不能实现: ``` rust @@ -216,7 +216,7 @@ 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的相关教程看一下,可能很早就发现这个问题, @@ -224,5 +224,5 @@ Could not compile `db`. 导致出现这样的问题,浪费很多的时间。 - 改变思维,把自己当作一个全新的新手,既要利用已有的思想来学习新的语言,同样不要 -被自己很精通的语言,固话自己的思维。 +被自己很精通的语言,固化自己的思维。 diff --git a/generic/exercise/Cargo.toml b/generic/exercise/Cargo.toml new file mode 100644 index 0000000..ccdf4f9 --- /dev/null +++ b/generic/exercise/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "exercise" +version = "0.1.0" +authors = ["Knight "] + +[dependencies] diff --git a/generic/exercise/README.md b/generic/exercise/README.md new file mode 100644 index 0000000..c05eadd --- /dev/null +++ b/generic/exercise/README.md @@ -0,0 +1,4 @@ +README +======= + +`cargo run` diff --git a/generic/exercise/src/main.rs b/generic/exercise/src/main.rs new file mode 100644 index 0000000..3bdf62f --- /dev/null +++ b/generic/exercise/src/main.rs @@ -0,0 +1,6 @@ +mod problem1; + +fn main() { + problem1::demo("Cargo.toml"); + problem1::demo(""); +} diff --git a/generic/exercise/src/problem1.rs b/generic/exercise/src/problem1.rs new file mode 100644 index 0000000..cc9f3e9 --- /dev/null +++ b/generic/exercise/src/problem1.rs @@ -0,0 +1,24 @@ +use std::borrow::Borrow; +use std::fs::File; +use std::io::{BufRead, BufReader}; + +fn parse(lines: I) + where I: IntoIterator, I::Item: Borrow +{ + 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()))); + } +} diff --git a/generic/generic.md b/generic/generic.md index ee8ed24..ec85110 100644 --- a/generic/generic.md +++ b/generic/generic.md @@ -78,9 +78,9 @@ fn main() { } ``` ->**输出:** ->101 ->200.33 +>**输出:** +>101 +>200.33 ```add>(a:T, b:T) -> T```就是我们泛型函数,返回值也是泛型T,Add<>中的含义可以暂时忽略,大体意思就是只要参数类型实现了Add trait,就可以被传入到我们的add函数,因为我们的add函数中有相加+操作,所以要求传进来的参数类型必须是可相加的,也就是必须实现了Add trait(具体参考std::ops::Add)。 @@ -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相关章节。 @@ -162,9 +162,9 @@ 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做了泛型化。 @@ -172,3 +172,39 @@ Point { x: 3, y: 3 } ### 总结 上面区区几十行的代码,却实现了非泛型语言百行甚至千行代码才能达到的效果,足见泛型的强大。 + +### 习题 + +#### 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 应该能派上用场.