[Rust] チュートリアル③ 入出力プロジェクト〜イテレータ

# はじめに
Rustのチュートリアルのメモです③。


# リンク集

[C++入門](https://amzn.to/2Nf1ntW)
[プログラミングRust (日本語) ](https://amzn.to/2Bs7vvS)
[プログラミング言語Rust入門](https://amzn.to/2BkGP0n)
[実践Rust入門](https://amzn.to/2zRbu4W)

[std::検索](https://doc.rust-lang.org/stable/std/)


# 入出力プロジェクト：コマンドラインプログラムを構築する

grepプロジェクトは、ここまでに学んできた多くの概念を集結させる

- コードを体系化する(モジュール)
- ベクタと文字列を使用する(コレクション)
- エラーを処理する
- 適切な箇所でトレイトとライフタイムを使用する
- テストを記述する


## 引数の値を読み取る

Rustの標準ライブラリで提供されているstd::env::args関数を用いる
この関数は、minigrepに与えられたコマンドライン引数のイテレータを変えす
イテレータは一連の値を生成する、イテレータに対してcollect関数を呼び出し、イテレータが生成する要素全部を含むベクタなどのコレクションに変えられる


```rust
use std::env;

fn main() {
	// 引数を受け取る
	let args: Vec<String> = env::args().collect();

	// 引数の値を変数に保存する
	let query = &args[1];
	let filename = &args[2];

	// {}を探しています
	println!("Searching for {}", query);
	// {}というファイルの中
	println!("In file {}", filename);
}
```


## リファクタリングしてモジュール性とエラー処理を向上させる

1つ目の問題: 
機能を小分けにすることで、各関数が１つの仕事のみに責任を持つようになり、関数の動作の正しさを確認することがしやすくなり、テストも行いやすくなり、機能を壊さずに変更できるようになるなり。

２つ目の問題:
mainが長くなるほど、スコープに入れるべき変数も増える
そして、スコープにある変数が増えれば、各々の目的を追うのも大変になる
設定用変数を１つの構造に押し込め、目的を明確化するのが最善

3つ目の問題:
ファイルを開く行為は、ファイルが存在しない以外にもいろんな方法で失敗することがある
例えば、ファイルは存在しても開く権限がないなど
「ファイルが見つかりませんでした」のみのエラー文だと、ユーザに間違った情報を与える

４つ目の問題:
異なるエラーを処理するのにexpectを繰り返し使用しているので、ユーザが十分な数の引数を渡さずにプログラムを起動した時に、問題を明確に説明しない「範囲外のアクセス(out of bounds)」というエラーがRustから得られる
エラー処理のコードが全て１箇所に存在し、将来エラー処理ロジックが変更になった時に、メンテナンス者が１箇所のコードのみを考慮すればいいようにするのが最善


### バイナリプロジェクトの責任の分離

main関数に複数の仕事の責任を割り当てるという構造上の問題は、多くのバイナリプロジェクトであふれている
結果として、mainが肥大化し始めた際にバイナリプログラムの個別の責任を分割するためにガイドラインとして活用できる工程をRustコミュニティは開発した

- プログラムをmain.rsとlib.rsに分け、ロジックをlib.rsに移動する
- コマンドライン引数の解析ロジックが小規模な限り、main.rsにおいても良い
- コマンドライン引数の解析ロジックが複雑化の様相を停止初めたら、main.rsから抽出してlib.rsに移動する


この工程の後に、main関数に残る責任は以下に限定される

- 引数の値でコマンドライン引数の解析ロジックを呼び出す
- 他のあらゆる設定を行う
- lib.rsのrun関数を呼び出す
- runがエラーを返した時に処理する


#### step1 引数解析機を抽出する

引数の値を変数に保存して返す関数を作成する

```rust

fn main() {
	let args: Vec<String> = env::args().collect();
	let (query, filename) = parse_config(&args);

	// 引数解析機
	fn parse_config(args: &[String]) -> (&str, &str) {
		let query = &args[1];
		let filename = &args[2];

		(query, filename)
	}
}
```


### step2 設定値をまとめる

関数がタプルを返し、即座にタプルを分解して再度個別の値にしている...これは、正しい抽象化をまだできていないかもしれない兆候

まだ改善の余地があると示してくれる他の兆候は、parse_configのconfigの部分、返却している２つの値は関係があり、１つの設定値の１部にどちらもなることを暗示している

この２つの値を１構造体に置き換え、構造体のフィールドそれぞれに意味のある名前をつけることもできる
そうすることで将来このコードのメンテナンス者が、異なる値が相互に関係する仕方や、目的を理解しやすくなる


```rust
fn main() {
    let args: Vec<String> = env::args().collect();

    let config = parse_config(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    // --snip--
}

struct Config {
    query: String,
    filename: String,
}

// parse_configのシグニチャは、これでConfig値を返すようになった
fn parse_config(args: &[String]) -> Config {
	// cloneによって参照のライフタイムを管理する必要がなくなる
	// が、Configインスタンスが所有するデータの総コピーが生成されるので、文字列データへの参照を保持するよりも時間とメモリを消費する
    let query = args[1].clone(); // 
    let filename = args[2].clone();

    Config { query, filename }
}
```

### Configのコンストラクタを作成する

今やparse_config関数の目的はConfigインスタンスを生成することになったので、parse_configをただの関数からConfig構造体に紐づくnewという関数に変えることができる
この変更によって、コードがより慣習的になる
String::newと同様に、Config::newで呼び出せるようになる

```rust
fn main() {
	let args: Vec<String> = env::args().collect();
	let config = Config::new(&args);)

	// -- snip ---
}

// -- snip --



### エラー処理を修正する

ベクタが引数が２個以下の要素しか含んでいない時にargsベクタの添字1か2にアクセスしようとすると、プログラムがパニックする(out of bounds)


### エラーメッセージを改善する

new関数に、添字１と２にアクセスする前にスライスが十分ながいことを実証するチェックをする、スライスの長さが足りなければ、エラーメッセージを表示する

```rust
fn new(args: &[String]) -> Config {
	if argsl.len() < 3 {
		panic!("not enough arguments");
	}
}

### panic!を呼び出す代わりにnewからResultを返す

成功時に、Configインスタンスを含み、エラー時には問題に言及するResult値を返すようにする

Config::newからErr値を返すことにより、main関数は、new関数から返ってくるResult値を処理し、エラー時により綺麗にプロセスから抜け出すことができる

```rust
impl Config{

	// &'static strは文字列リテラル型(今回のエラーメッセージの型)
	
	fn new(args: &[String]) -> Result<Config, &'static str> {
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		// -- snip --	
		Ok(Config { query, filename })
	}
}


### Config::newを呼び出し、エラー処理をす

Configの戻り値が変更したので、mainの処理を変更する必要がある

unwrap_or_elseを用い、独自のエラー処理を定義できる

unwrapは、Ok値の時にOkが包んでいる中身を返す

unwrap_or_elseは、Err値なら、このメソッドの場合、クロージャ内でコードを呼び出し、クロージャによってプログラムを綺麗に終了させる


### mainからロジックを抽出する

現在main関数に存在する設定のセットアップやエラー処理にかかわらない全てのロジックを保持することになるrunという関数を抽出する

```rust
fn main() {
    // --snip--

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    run(config);
}

fn run(config: Config) {
    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents)
        .expect("something went wrong reading the file");

    println!("With text:\n{}", contents);
}

// --snip--
```


### run関数からエラーを返す

Box<Error>は、関数がErrorトレイトを実装する型を返すことを意味する
戻り値の型を具体的に指定しなくても良い
これにより、エラーケースによって異なる型のエラー値を返す柔軟性を得る


```rust
fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からエラー値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	f.read_to_string(&mut contents)?;

	println!("With text:\n{}", contents);

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}
```

### mainでrunから返ってきたエラーを処理する

```rust
if let Err(e) = run(config) {
	println!(Application error: {}", e);
	process:exit(1);
}
```


## テスト開発駆動でライブラリの機能を開発する

1. 失敗するテストを書き、走らせて想定通りの理由で失敗することを確かめる
2. 十分な量のコードを書くか変更して新しいテストを通過するようにする
3. 追加または変更したばかりのコードをリファクタリングし、テストが通り続けることを確認する
4. 手順1から繰り返す


### 失敗するテストを記述する

search関数が未実装なのでテストどころかコンパイルが通らない

```rust:src/lib.rs
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        // Rustは
        // 安全で速く生産性も高い。
        // 3つ選んで。
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }
}
```

search関数を実装する

```rust
// 'aがserachのシグネチャで定義し、contents引数と戻り値で使用する
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	vec![]
}
```


## 環境変数を取り扱う

1. 大小小文字を区別しないsearch関数用に失敗するテストを書く
2. Config構造体にinsensitiveを追加　
3. impl Configでenv:varを用いて環境変数を確認する
4. シェルでrcファイルに環境変数を追記する
5. 成功するテストを完成させる

```rust
pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
	pub fn new(args: &[String]) -> Result<Config, &'static str> {
		// スライス長が十分でなければエラー
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		let query = args[1].clone();
		let filename = args[2].clone();

		// 環境変数CASE_INSENSITIVEが何かにセットされていれば
		// falseを返す
		let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

		Ok(Config {
			query,
			filename,
			case_sensitive, // 追加
		})
	}
}

pub fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からError値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	// contentsに読み込んだfを文字列に変換して入れる
	f.read_to_string(&mut contents)?;

	// 環境変数に応じて処理を分岐
	let results = if config.case_sensitive {
		search_case_sensitive(&config.query, &contents)
	} else {
		search_case_insensitive(&config.query, &contents)
	};

	for line in results {
		println!("{}", line);
	}

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}


// メソッド名を変更
pub fn search_case_sensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
// -- snip --
}

// 大小文字を区別しないsearch関数
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	let query = query.to_lowercase();
	let mut results = Vec::new();

	for line in contents.lines() {
		if line.to_lowercase().contains(&query) {
			results.push(line);
		}
	}

	results
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn case_sensitive() {
		let query = "duct";
		let contents = "\
Rust:
safe, fast, productive.
Pick three.:";
		assert_eq!(
			vec!["safe, fast, productive."],
			search_case_sensitive(query, contents)
		);
	}

	#[test]
	fn case_insensitive() {
		let query = "rUsT";
		// (最後の行のみ)
		// 私を信じて
		let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

		assert_eq!(
			vec!["Rust:", "Trust me."],
			search_case_insensitive(query, contents)
		);
	}
}
```


```
$ CASE_INSENSITIVE=1 cargo run to poem.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/minigrep to poem.txt`
Are you nobody, too?
How dreary to be somebody!
To tell your name the livelong day
To an admiring bog!
```


## 標準出力ではなく標準エラーにエラーメッセージを書き込む

現時点では、すべての出力をprintln!関数を使用して端末に書き込んでいる

多くの端末は２種類の出力を提供する

普通の情報用の標準出力(stdout)とエラーメッセージ用の標準エラー出力(stderr)

この差異のおかげで、ユーザはエラーメッセージを画面に表示しつつ、プログラムの成功した出力をファイルにリダイレクトすることを選択できる

prinln!関数は、標準出力に出力する能力しか無いので、標準エラーに出力するには他のものを使用しなければならない


### エラーが書き込まれる場所を確認する

```
$ cargo run > output.txt
```

```text:output.txt
Problem parsing arguments: not enough arguments
```

プロジェクトルートにファイルが作成されている


### エーラを標準エラーに出力する

```rust
fn main() {
	let args: Vec<String> = env::args().collect();

	let config = Config::new(&args).unwrap_or_else(|err| {
		// エラーは画面にみえつつ、output.txtは何も含まない
		// 成功のときはは、画面に見えず、output.txtに結果が含まれる
		// これはコマンドラインプログラムに期待する動作
		eprintln!("Problem parseing argumetns: {}", err);
		process::exit(1);
	);
}
```

# 入出力プロジェクト：コマンドラインプログラムを構築する

grepプロジェクトは、ここまでに学んできた多くの概念を集結させる

- コードを体系化する(モジュール)
- ベクタと文字列を使用する(コレクション)
- エラーを処理する
- 適切な箇所でトレイトとライフタイムを使用する
- テストを記述する


## 引数の値を読み取る

Rustの標準ライブラリで提供されているstd::env::args関数を用いる
この関数は、minigrepに与えられたコマンドライン引数のイテレータを変えす
イテレータは一連の値を生成する、イテレータに対してcollect関数を呼び出し、イテレータが生成する要素全部を含むベクタなどのコレクションに変えられる


```rust
use std::env;

fn main() {
	// 引数を受け取る
	let args: Vec<String> = env::args().collect();

	// 引数の値を変数に保存する
	let query = &args[1];
	let filename = &args[2];

	// {}を探しています
	println!("Searching for {}", query);
	// {}というファイルの中
	println!("In file {}", filename);
}
```


## リファクタリングしてモジュール性とエラー処理を向上させる

1つ目の問題: 
機能を小分けにすることで、各関数が１つの仕事のみに責任を持つようになり、関数の動作の正しさを確認することがしやすくなり、テストも行いやすくなり、機能を壊さずに変更できるようになるなり。

２つ目の問題:
mainが長くなるほど、スコープに入れるべき変数も増える
そして、スコープにある変数が増えれば、各々の目的を追うのも大変になる
設定用変数を１つの構造に押し込め、目的を明確化するのが最善

3つ目の問題:
ファイルを開く行為は、ファイルが存在しない以外にもいろんな方法で失敗することがある
例えば、ファイルは存在しても開く権限がないなど
「ファイルが見つかりませんでした」のみのエラー文だと、ユーザに間違った情報を与える

４つ目の問題:
異なるエラーを処理するのにexpectを繰り返し使用しているので、ユーザが十分な数の引数を渡さずにプログラムを起動した時に、問題を明確に説明しない「範囲外のアクセス(out of bounds)」というエラーがRustから得られる
エラー処理のコードが全て１箇所に存在し、将来エラー処理ロジックが変更になった時に、メンテナンス者が１箇所のコードのみを考慮すればいいようにするのが最善


### バイナリプロジェクトの責任の分離

main関数に複数の仕事の責任を割り当てるという構造上の問題は、多くのバイナリプロジェクトであふれている
結果として、mainが肥大化し始めた際にバイナリプログラムの個別の責任を分割するためにガイドラインとして活用できる工程をRustコミュニティは開発した

- プログラムをmain.rsとlib.rsに分け、ロジックをlib.rsに移動する
- コマンドライン引数の解析ロジックが小規模な限り、main.rsにおいても良い
- コマンドライン引数の解析ロジックが複雑化の様相を停止初めたら、main.rsから抽出してlib.rsに移動する


この工程の後に、main関数に残る責任は以下に限定される

- 引数の値でコマンドライン引数の解析ロジックを呼び出す
- 他のあらゆる設定を行う
- lib.rsのrun関数を呼び出す
- runがエラーを返した時に処理する


#### step1 引数解析機を抽出する

引数の値を変数に保存して返す関数を作成する

```rust

fn main() {
	let args: Vec<String> = env::args().collect();
	let (query, filename) = parse_config(&args);

	// 引数解析機
	fn parse_config(args: &[String]) -> (&str, &str) {
		let query = &args[1];
		let filename = &args[2];

		(query, filename)
	}
}
```


### step2 設定値をまとめる

関数がタプルを返し、即座にタプルを分解して再度個別の値にしている...これは、正しい抽象化をまだできていないかもしれない兆候

まだ改善の余地があると示してくれる他の兆候は、parse_configのconfigの部分、返却している２つの値は関係があり、１つの設定値の１部にどちらもなることを暗示している

この２つの値を１構造体に置き換え、構造体のフィールドそれぞれに意味のある名前をつけることもできる
そうすることで将来このコードのメンテナンス者が、異なる値が相互に関係する仕方や、目的を理解しやすくなる


```rust
fn main() {
    let args: Vec<String> = env::args().collect();

    let config = parse_config(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    // --snip--
}

struct Config {
    query: String,
    filename: String,
}

// parse_configのシグニチャは、これでConfig値を返すようになった
fn parse_config(args: &[String]) -> Config {
	// cloneによって参照のライフタイムを管理する必要がなくなる
	// が、Configインスタンスが所有するデータの総コピーが生成されるので、文字列データへの参照を保持するよりも時間とメモリを消費する
    let query = args[1].clone(); // 
    let filename = args[2].clone();

    Config { query, filename }
}
```

### Configのコンストラクタを作成する

今やparse_config関数の目的はConfigインスタンスを生成することになったので、parse_configをただの関数からConfig構造体に紐づくnewという関数に変えることができる
この変更によって、コードがより慣習的になる
String::newと同様に、Config::newで呼び出せるようになる

```rust
fn main() {
	let args: Vec<String> = env::args().collect();
	let config = Config::new(&args);)

	// -- snip ---
}

// -- snip --



### エラー処理を修正する

ベクタが引数が２個以下の要素しか含んでいない時にargsベクタの添字1か2にアクセスしようとすると、プログラムがパニックする(out of bounds)


### エラーメッセージを改善する

new関数に、添字１と２にアクセスする前にスライスが十分ながいことを実証するチェックをする、スライスの長さが足りなければ、エラーメッセージを表示する

```rust
fn new(args: &[String]) -> Config {
	if argsl.len() < 3 {
		panic!("not enough arguments");
	}
}

### panic!を呼び出す代わりにnewからResultを返す

成功時に、Configインスタンスを含み、エラー時には問題に言及するResult値を返すようにする

Config::newからErr値を返すことにより、main関数は、new関数から返ってくるResult値を処理し、エラー時により綺麗にプロセスから抜け出すことができる

```rust
impl Config{

	// &'static strは文字列リテラル型(今回のエラーメッセージの型)
	
	fn new(args: &[String]) -> Result<Config, &'static str> {
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		// -- snip --	
		Ok(Config { query, filename })
	}
}


### Config::newを呼び出し、エラー処理をす

Configの戻り値が変更したので、mainの処理を変更する必要がある

unwrap_or_elseを用い、独自のエラー処理を定義できる

unwrapは、Ok値の時にOkが包んでいる中身を返す

unwrap_or_elseは、Err値なら、このメソッドの場合、クロージャ内でコードを呼び出し、クロージャによってプログラムを綺麗に終了させる


### mainからロジックを抽出する

現在main関数に存在する設定のセットアップやエラー処理にかかわらない全てのロジックを保持することになるrunという関数を抽出する

```rust
fn main() {
    // --snip--

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    run(config);
}

fn run(config: Config) {
    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents)
        .expect("something went wrong reading the file");

    println!("With text:\n{}", contents);
}

// --snip--
```


### run関数からエラーを返す

Box<Error>は、関数がErrorトレイトを実装する型を返すことを意味する
戻り値の型を具体的に指定しなくても良い
これにより、エラーケースによって異なる型のエラー値を返す柔軟性を得る


```rust
fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からエラー値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	f.read_to_string(&mut contents)?;

	println!("With text:\n{}", contents);

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}
```

### mainでrunから返ってきたエラーを処理する

```rust
if let Err(e) = run(config) {
	println!(Application error: {}", e);
	process:exit(1);
}
```


## テスト開発駆動でライブラリの機能を開発する

1. 失敗するテストを書き、走らせて想定通りの理由で失敗することを確かめる
2. 十分な量のコードを書くか変更して新しいテストを通過するようにする
3. 追加または変更したばかりのコードをリファクタリングし、テストが通り続けることを確認する
4. 手順1から繰り返す


### 失敗するテストを記述する

search関数が未実装なのでテストどころかコンパイルが通らない

```rust:src/lib.rs
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        // Rustは
        // 安全で速く生産性も高い。
        // 3つ選んで。
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }
}
```

search関数を実装する

```rust
// 'aがserachのシグネチャで定義し、contents引数と戻り値で使用する
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	vec![]
}
```


## 環境変数を取り扱う

1. 大小小文字を区別しないsearch関数用に失敗するテストを書く
2. Config構造体にinsensitiveを追加　
3. impl Configでenv:varを用いて環境変数を確認する
4. シェルでrcファイルに環境変数を追記する
5. 成功するテストを完成させる

```rust
pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
	pub fn new(args: &[String]) -> Result<Config, &'static str> {
		// スライス長が十分でなければエラー
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		let query = args[1].clone();
		let filename = args[2].clone();

		// 環境変数CASE_INSENSITIVEが何かにセットされていれば
		// falseを返す
		let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

		Ok(Config {
			query,
			filename,
			case_sensitive, // 追加
		})
	}
}

pub fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からError値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	// contentsに読み込んだfを文字列に変換して入れる
	f.read_to_string(&mut contents)?;

	// 環境変数に応じて処理を分岐
	let results = if config.case_sensitive {
		search_case_sensitive(&config.query, &contents)
	} else {
		search_case_insensitive(&config.query, &contents)
	};

	for line in results {
		println!("{}", line);
	}

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}


// メソッド名を変更
pub fn search_case_sensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
// -- snip --
}

// 大小文字を区別しないsearch関数
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	let query = query.to_lowercase();
	let mut results = Vec::new();

	for line in contents.lines() {
		if line.to_lowercase().contains(&query) {
			results.push(line);
		}
	}

	results
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn case_sensitive() {
		let query = "duct";
		let contents = "\
Rust:
safe, fast, productive.
Pick three.:";
		assert_eq!(
			vec!["safe, fast, productive."],
			search_case_sensitive(query, contents)
		);
	}

	#[test]
	fn case_insensitive() {
		let query = "rUsT";
		// (最後の行のみ)
		// 私を信じて
		let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

		assert_eq!(
			vec!["Rust:", "Trust me."],
			search_case_insensitive(query, contents)
		);
	}
}
```


```
$ CASE_INSENSITIVE=1 cargo run to poem.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/minigrep to poem.txt`
Are you nobody, too?
How dreary to be somebody!
To tell your name the livelong day
To an admiring bog!
```


## 標準出力ではなく標準エラーにエラーメッセージを書き込む

現時点では、すべての出力をprintln!関数を使用して端末に書き込んでいる

多くの端末は２種類の出力を提供する

普通の情報用の標準出力(stdout)とエラーメッセージ用の標準エラー出力(stderr)

この差異のおかげで、ユーザはエラーメッセージを画面に表示しつつ、プログラムの成功した出力をファイルにリダイレクトすることを選択できる

prinln!関数は、標準出力に出力する能力しか無いので、標準エラーに出力するには他のものを使用しなければならない


### エラーが書き込まれる場所を確認する

```
$ cargo run > output.txt
```

```text:output.txt
Problem parsing arguments: not enough arguments
```

プロジェクトルートにファイルが作成されている


### エーラを標準エラーに出力する

```rust
fn main() {
	let args: Vec<String> = env::args().collect();

	let config = Config::new(&args).unwrap_or_else(|err| {
		// エラーは画面にみえつつ、output.txtは何も含まない
		// 成功のときはは、画面に見えず、output.txtに結果が含まれる
		// これはコマンドラインプログラムに期待する動作
		eprintln!("Problem parseing argumetns: {}", err);
		process::exit(1);
	);
}
```



# 入出力プロジェクト：コマンドラインプログラムを構築する

grepプロジェクトは、ここまでに学んできた多くの概念を集結させる

- コードを体系化する(モジュール)
- ベクタと文字列を使用する(コレクション)
- エラーを処理する
- 適切な箇所でトレイトとライフタイムを使用する
- テストを記述する


## 引数の値を読み取る

Rustの標準ライブラリで提供されているstd::env::args関数を用いる
この関数は、minigrepに与えられたコマンドライン引数のイテレータを変えす
イテレータは一連の値を生成する、イテレータに対してcollect関数を呼び出し、イテレータが生成する要素全部を含むベクタなどのコレクションに変えられる


```rust
use std::env;

fn main() {
	// 引数を受け取る
	let args: Vec<String> = env::args().collect();

	// 引数の値を変数に保存する
	let query = &args[1];
	let filename = &args[2];

	// {}を探しています
	println!("Searching for {}", query);
	// {}というファイルの中
	println!("In file {}", filename);
}
```


## リファクタリングしてモジュール性とエラー処理を向上させる

1つ目の問題: 
機能を小分けにすることで、各関数が１つの仕事のみに責任を持つようになり、関数の動作の正しさを確認することがしやすくなり、テストも行いやすくなり、機能を壊さずに変更できるようになるなり。

２つ目の問題:
mainが長くなるほど、スコープに入れるべき変数も増える
そして、スコープにある変数が増えれば、各々の目的を追うのも大変になる
設定用変数を１つの構造に押し込め、目的を明確化するのが最善

3つ目の問題:
ファイルを開く行為は、ファイルが存在しない以外にもいろんな方法で失敗することがある
例えば、ファイルは存在しても開く権限がないなど
「ファイルが見つかりませんでした」のみのエラー文だと、ユーザに間違った情報を与える

４つ目の問題:
異なるエラーを処理するのにexpectを繰り返し使用しているので、ユーザが十分な数の引数を渡さずにプログラムを起動した時に、問題を明確に説明しない「範囲外のアクセス(out of bounds)」というエラーがRustから得られる
エラー処理のコードが全て１箇所に存在し、将来エラー処理ロジックが変更になった時に、メンテナンス者が１箇所のコードのみを考慮すればいいようにするのが最善


### バイナリプロジェクトの責任の分離

main関数に複数の仕事の責任を割り当てるという構造上の問題は、多くのバイナリプロジェクトであふれている
結果として、mainが肥大化し始めた際にバイナリプログラムの個別の責任を分割するためにガイドラインとして活用できる工程をRustコミュニティは開発した

- プログラムをmain.rsとlib.rsに分け、ロジックをlib.rsに移動する
- コマンドライン引数の解析ロジックが小規模な限り、main.rsにおいても良い
- コマンドライン引数の解析ロジックが複雑化の様相を停止初めたら、main.rsから抽出してlib.rsに移動する


この工程の後に、main関数に残る責任は以下に限定される

- 引数の値でコマンドライン引数の解析ロジックを呼び出す
- 他のあらゆる設定を行う
- lib.rsのrun関数を呼び出す
- runがエラーを返した時に処理する


#### step1 引数解析機を抽出する

引数の値を変数に保存して返す関数を作成する

```rust

fn main() {
	let args: Vec<String> = env::args().collect();
	let (query, filename) = parse_config(&args);

	// 引数解析機
	fn parse_config(args: &[String]) -> (&str, &str) {
		let query = &args[1];
		let filename = &args[2];

		(query, filename)
	}
}
```


### step2 設定値をまとめる

関数がタプルを返し、即座にタプルを分解して再度個別の値にしている...これは、正しい抽象化をまだできていないかもしれない兆候

まだ改善の余地があると示してくれる他の兆候は、parse_configのconfigの部分、返却している２つの値は関係があり、１つの設定値の１部にどちらもなることを暗示している

この２つの値を１構造体に置き換え、構造体のフィールドそれぞれに意味のある名前をつけることもできる
そうすることで将来このコードのメンテナンス者が、異なる値が相互に関係する仕方や、目的を理解しやすくなる


```rust
fn main() {
    let args: Vec<String> = env::args().collect();

    let config = parse_config(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    // --snip--
}

struct Config {
    query: String,
    filename: String,
}

// parse_configのシグニチャは、これでConfig値を返すようになった
fn parse_config(args: &[String]) -> Config {
	// cloneによって参照のライフタイムを管理する必要がなくなる
	// が、Configインスタンスが所有するデータの総コピーが生成されるので、文字列データへの参照を保持するよりも時間とメモリを消費する
    let query = args[1].clone(); // 
    let filename = args[2].clone();

    Config { query, filename }
}
```

### Configのコンストラクタを作成する

今やparse_config関数の目的はConfigインスタンスを生成することになったので、parse_configをただの関数からConfig構造体に紐づくnewという関数に変えることができる
この変更によって、コードがより慣習的になる
String::newと同様に、Config::newで呼び出せるようになる

```rust
fn main() {
	let args: Vec<String> = env::args().collect();
	let config = Config::new(&args);)

	// -- snip ---
}

// -- snip --



### エラー処理を修正する

ベクタが引数が２個以下の要素しか含んでいない時にargsベクタの添字1か2にアクセスしようとすると、プログラムがパニックする(out of bounds)


### エラーメッセージを改善する

new関数に、添字１と２にアクセスする前にスライスが十分ながいことを実証するチェックをする、スライスの長さが足りなければ、エラーメッセージを表示する

```rust
fn new(args: &[String]) -> Config {
	if argsl.len() < 3 {
		panic!("not enough arguments");
	}
}

### panic!を呼び出す代わりにnewからResultを返す

成功時に、Configインスタンスを含み、エラー時には問題に言及するResult値を返すようにする

Config::newからErr値を返すことにより、main関数は、new関数から返ってくるResult値を処理し、エラー時により綺麗にプロセスから抜け出すことができる

```rust
impl Config{

	// &'static strは文字列リテラル型(今回のエラーメッセージの型)
	
	fn new(args: &[String]) -> Result<Config, &'static str> {
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		// -- snip --	
		Ok(Config { query, filename })
	}
}


### Config::newを呼び出し、エラー処理をす

Configの戻り値が変更したので、mainの処理を変更する必要がある

unwrap_or_elseを用い、独自のエラー処理を定義できる

unwrapは、Ok値の時にOkが包んでいる中身を返す

unwrap_or_elseは、Err値なら、このメソッドの場合、クロージャ内でコードを呼び出し、クロージャによってプログラムを綺麗に終了させる


### mainからロジックを抽出する

現在main関数に存在する設定のセットアップやエラー処理にかかわらない全てのロジックを保持することになるrunという関数を抽出する

```rust
fn main() {
    // --snip--

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    run(config);
}

fn run(config: Config) {
    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents)
        .expect("something went wrong reading the file");

    println!("With text:\n{}", contents);
}

// --snip--
```


### run関数からエラーを返す

Box<Error>は、関数がErrorトレイトを実装する型を返すことを意味する
戻り値の型を具体的に指定しなくても良い
これにより、エラーケースによって異なる型のエラー値を返す柔軟性を得る


```rust
fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からエラー値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	f.read_to_string(&mut contents)?;

	println!("With text:\n{}", contents);

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}
```

### mainでrunから返ってきたエラーを処理する

```rust
if let Err(e) = run(config) {
	println!(Application error: {}", e);
	process:exit(1);
}
```


## テスト開発駆動でライブラリの機能を開発する

1. 失敗するテストを書き、走らせて想定通りの理由で失敗することを確かめる
2. 十分な量のコードを書くか変更して新しいテストを通過するようにする
3. 追加または変更したばかりのコードをリファクタリングし、テストが通り続けることを確認する
4. 手順1から繰り返す


### 失敗するテストを記述する

search関数が未実装なのでテストどころかコンパイルが通らない

```rust:src/lib.rs
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        // Rustは
        // 安全で速く生産性も高い。
        // 3つ選んで。
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }
}
```

search関数を実装する

```rust
// 'aがserachのシグネチャで定義し、contents引数と戻り値で使用する
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	vec![]
}
```


## 環境変数を取り扱う

1. 大小小文字を区別しないsearch関数用に失敗するテストを書く
2. Config構造体にinsensitiveを追加　
3. impl Configでenv:varを用いて環境変数を確認する
4. シェルでrcファイルに環境変数を追記する
5. 成功するテストを完成させる

```rust
pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
	pub fn new(args: &[String]) -> Result<Config, &'static str> {
		// スライス長が十分でなければエラー
		if args.len() < 3 {
			return Err("not enough arguments");
		}
		let query = args[1].clone();
		let filename = args[2].clone();

		// 環境変数CASE_INSENSITIVEが何かにセットされていれば
		// falseを返す
		let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

		Ok(Config {
			query,
			filename,
			case_sensitive, // 追加
		})
	}
}

pub fn run(config: Config) -> Result<(), Box<Error>> {
	// expectを呼び出してパニックさせるかわりに
	// ?演算子で呼び出し元が処理できるように、現在の関数からError値を返す
	let mut f = File::open(config.filename)?;

	let mut contents = String::new();
	// expect → ?
	// contentsに読み込んだfを文字列に変換して入れる
	f.read_to_string(&mut contents)?;

	// 環境変数に応じて処理を分岐
	let results = if config.case_sensitive {
		search_case_sensitive(&config.query, &contents)
	} else {
		search_case_insensitive(&config.query, &contents)
	};

	for line in results {
		println!("{}", line);
	}

	// (())という記法は、runを副作用のためだけに呼び出していると示唆する慣習的な方法
	Ok(())
}


// メソッド名を変更
pub fn search_case_sensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
// -- snip --
}

// 大小文字を区別しないsearch関数
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
	let query = query.to_lowercase();
	let mut results = Vec::new();

	for line in contents.lines() {
		if line.to_lowercase().contains(&query) {
			results.push(line);
		}
	}

	results
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn case_sensitive() {
		let query = "duct";
		let contents = "\
Rust:
safe, fast, productive.
Pick three.:";
		assert_eq!(
			vec!["safe, fast, productive."],
			search_case_sensitive(query, contents)
		);
	}

	#[test]
	fn case_insensitive() {
		let query = "rUsT";
		// (最後の行のみ)
		// 私を信じて
		let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

		assert_eq!(
			vec!["Rust:", "Trust me."],
			search_case_insensitive(query, contents)
		);
	}
}
```


```
$ CASE_INSENSITIVE=1 cargo run to poem.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/minigrep to poem.txt`
Are you nobody, too?
How dreary to be somebody!
To tell your name the livelong day
To an admiring bog!
```


## 標準出力ではなく標準エラーにエラーメッセージを書き込む

現時点では、すべての出力をprintln!関数を使用して端末に書き込んでいる

多くの端末は２種類の出力を提供する

普通の情報用の標準出力(stdout)とエラーメッセージ用の標準エラー出力(stderr)

この差異のおかげで、ユーザはエラーメッセージを画面に表示しつつ、プログラムの成功した出力をファイルにリダイレクトすることを選択できる

prinln!関数は、標準出力に出力する能力しか無いので、標準エラーに出力するには他のものを使用しなければならない


### エラーが書き込まれる場所を確認する

```
$ cargo run > output.txt
```

```text:output.txt
Problem parsing arguments: not enough arguments
```

プロジェクトルートにファイルが作成されている


### エーラを標準エラーに出力する

```rust
fn main() {
	let args: Vec<String> = env::args().collect();

	let config = Config::new(&args).unwrap_or_else(|err| {
		// エラーは画面にみえつつ、output.txtは何も含まない
		// 成功のときはは、画面に見えず、output.txtに結果が含まれる
		// これはコマンドラインプログラムに期待する動作
		eprintln!("Problem parseing argumetns: {}", err);
		process::exit(1);
	);
}
```


# 関数言語の機能：　イテレータとクロージャ

クロージャとイテレータをマスターすることは、慣用的で早いRustコードを書くことで重要

クロージャ: 変数に保存できる関数に似た文法要素
イテレータ: 一連の要素を処理する方法
その他: パターンパッチング、enum

低レベルのパフォーマンスで、高レベルの考えを明確に表現するというのがRustの能力に貢献している
クロージャとイテレータの実装は、実行時のパフォーマンスが影響されないようになっている
これは、ゼロ代償抽象化を提供するのに努力を惜しまないRustの目標の一部

## クロージャで動作の抽象化を行う

```rust

use std::thread;
use std::time::Duration;

// 標準出力して、２秒待ってから、渡した数値をなんでも返す関数
fn simulated_expensive_calculation(intensity: u32) -> u32 {
    // ゆっくり計算します
    println!("calculating slowly...");
    thread::sleep(Duration::from_secs(2));
    intensity
}

fn main() {
    let simulated_user_specified_value = 10;
    let simulated_random_number = 7;

    generate_workout(
        simulated_user_specified_value,
        simulated_random_number
    );
}
```


## クロージャでリファクタリングして、コードを保存する

```rust
fn generate_workout(intensity: u32, random_number: u32) {
	// ||は引数
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    };

    if intensity < 25 {
        println!(
            "Today, do {} pushups!",
            expensive_closure(intensity)
        );
        println!(
            "Next, do {} situps!",
            expensive_closure(intensity)
        );
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!(
                "Today, run for {} minutes!",
                expensive_closure(intensity)
            );
        }
    }
}
```

## クロージャの型推論と注釈

クロージャでは、fn関数のように引数の型や戻り値の型を注釈する必要はない

クロージャではコンパイラが型推論をおこなう

本当に必要な以上に冗長になることと引き換えに、明示生徒明瞭性を向上させたいなら、変数に型注釈を加えることもできる

```rust
let expensive_closure = |num: u32| -> u32 {
		println!("calculating slowly...");
		thread::sleep(Duration::from_secs(2));
		num
	};
```

```rust:関数とクロージャの比較
fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |xsl: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;
```


```rust:クロージャの型エラー
let example_closure = |x| x;

let s = example_closure( String::from("hello"));
// sの型推論でクロージャがStringと推測したため
// 数値を入れると型エラーとなる
let n = example_closure(5);
```


## ジェネリック引数とFnトレイトを使用してクロージャを保存する

重いクロージャの結果を再利用できるように変数に保存し、クロージャを再度呼ぶ代わりに、結果が必要になるか箇所でそれぞれでその変数を使用する
しかしながら、この方法は同じコードを大量に繰り返す化膿性がある

クロージャやクロージャの呼び出し結果の値を保持する構造体をつくれる
結果の値が必要な場合にのみその構造体はクロージャを実行し、その結果の値をキャッシュするので、残りのコードは、結果を保存し、再利用する責任を追わなくて済む

クロージャを保持する構造体を作成するために、クロージャの方を指定する必要がある構造体定義は、各フィールドの型を泊する必要があるから
各クロージャインスタンスには、独自の匿名の型がある
つまり、２つのクロージャが全く同じシグニチャでも、その型はそれでも違うものと考えられる


Cacher構造体は、ジェネリックな型Tのcalculationフィールドを持つ
Tのトレイト境界は、Fnトレイトを使うことでクロージャであると指定している
calculationフォールドに保存したいクロージャは全て、１つのu32の引数(Fnの後のカッコ内で指定している)を取り、u32(->のあとに指定されている)を返さなければならない

```rust
struct Cacher<T> where T: Fn(u32) -> u32 {
	calculation: T,     
	vlaue: Option<u32>, 
}


## イテレータ

```rust
fn main() {
	let v1 = vec![1, 2, 3];
	let mut v1_iter = v1.iter();
	assert_eq!(Some(&1), v1_iter.next());
	assert_eq!(Some(&2), v1_iter.next());
	assert_eq!(Some(&3), v1_iter.next());
}

next()の呼び出しで得られる値は、ベクタへの不変な参照


### イテレータを消費するメソッド

Iteratorトレイトには、標準ライブラリが提供してくれているデフォルト実装のある多くの異なるメソッドがある
これらのメソッドの中には、定義内でnextメソッドを呼ぶものもあり、故にiteratorトレイトを実装する際には、nextメソッドを実装する必要がある

nextを呼び出すメソッドは、消費アダプタ(consuming adaputors)と呼ばれる


## パフォーマンス比較: ループ VS イテレータ

イテレーションのほうが些か高速になる

```terminal:文字列を読み込むテスト
test bench_search_for  ... bench:  19,620,300 ns/iter (+/- 915,700)
test bench_search_iter ... bench:  19,234,900 ns/iter (+/- 657,200)
`