3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

rustとscalaとkotilnの勉強 数当てゲーム(rust) 2回目

Last updated at Posted at 2018-07-03

TRPLの数当てゲーム
scalaを書き直したので同じ感じでrustで書けないか試す。
ループを使わずに書くとどうなるか。

恥ずかしいけど載せる。
最初かいたのはこれ

extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
struct Gen<F>{
	f:F
}

impl<R,F:FnMut()->R> Iterator for Gen<F>{
	type Item=R;
	fn next(&mut self)->Option<R> { Some((self.f)()) }
}

fn main(){
	let secret_number = rand::thread_rng().gen_range(1,101);
	println!("秘密の数字は次の通り:{}",secret_number);
	println!("数をあててごらん");

	println!("ほら、予想を入力してね");

	(Gen{f:||{
				let mut guess = String::new();
				match io::stdin().read_line(&mut guess){
					Err(s) => Err(s),
					Ok(_) => Ok(guess)
				}
			}
		})
			.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
			.filter(|r| r.is_ok())
			.map(|r| r.unwrap() )
			.map(|u| match u.cmp(&secret_number){
						Ordering::Less => {println!("ちいさすぎる") ; u },
						Ordering::Greater => {println!("大き過ぎる") ; u },
						Ordering::Equal => {println!("正解"); u }
					})
			.filter(|u| u == &secret_number)
			.nth(0);
}

rustでクロージャをとってIteratorを返す方法がないかなーと調べたら

std::iter::repeat_with

が見つかったんだけどnightly-onlyだったのでやめ。
repeat_withをぱくってGenとして自作した。

https://qiita.com/ubnt_intrepid/items/df70da960b21b222d0ad
の最初の方だけ読んだけど、Python,C#,JavaScriptっぽいジェネレータ(yield)も入れようとしてるっぽい??
いつになるかはわからないけど。

で、、、とりあえず動かそうと思って書いたので見返すといろいろとアレだ。
まず、、、

				let mut guess = String::new();
				match io::stdin().read_line(&mut guess){
					Err(s) => Err(s),
					Ok(_) => Ok(guess)
				}

この辺
やりたいのはOkのときにOk(guess)に変えたいだけ。
Errはほっといていい。
ならread_lineの結果をmapすりゃよくね?
となって以下に変えた。

	(Gen{f:||{
				let mut guess = String::new();
				io::stdin().read_line(&mut guess).map(|_| guess)
			}
		})

うん。うごく。
あとなんとなく不安でGen{...}を()で囲ってる。
その後.flat_mapて書いてOKなのかわからなかったからとりあえず書いていた。

	(Gen{f:||{
				let mut guess = String::new();
				io::stdin().read_line(&mut guess).map(|_| guess)
			}
		})
			.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))

これも消してみる。

	Gen{f:||{
				let mut guess = String::new();
				io::stdin().read_line(&mut guess).map(|_| guess)
			}
		}
			.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))

いけるっぽい。

次。

	Gen{f:||{
				let mut guess = String::new();
				io::stdin().read_line(&mut guess).map(|_| guess)
			}
		}
			.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
			.filter(|r| r.is_ok())

なんかきもい。自分で穴掘って埋めてる感ある。
うーん。うまく言語化できない。
というかちゃんとダメなところが明確でないんだろうな。
考える。
んー。

だめ。時間切れ。
とりあえず以下になおした。
flat_map(|r| r)はflattenがnightlyだったから。

extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
struct Gen<F>{
	f:F
}

impl<R,F:FnMut()->R> Iterator for Gen<F>{
	type Item=R;
	fn next(&mut self)->Option<R> { Some((self.f)()) }
}

fn main(){
	let secret_number = rand::thread_rng().gen_range(1,101);
	println!("秘密の数字は次の通り:{}",secret_number);
	println!("数をあててごらん");
	println!("ほら、予想を入力してね");

	Gen{f:||{
				let mut guess = String::new();
				io::stdin().read_line(&mut guess)
					.map(|_| guess)
					.map(|s| s.trim().parse::<u32>())
			}
		}
		.flat_map(|r| r)
		.filter(|r| r.is_ok())
		.map(|r| r.unwrap() )
		.map(|u| match u.cmp(&secret_number){
						Ordering::Less => {println!("ちいさすぎる") ; u },
						Ordering::Greater => {println!("大き過ぎる") ; u },
						Ordering::Equal => {println!("正解"); u }
					})
			.filter(|u| u == &secret_number)
			.nth(0);
}
3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?