11
7

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に挑戦!新しいプログラミング言語を学ぶ15のエクササイズを解いてみた

Last updated at Posted at 2017-07-10

世の中には、Prashant N Mhatreさんによる、15 Exercises for learning new programming languagesというものがあるようです。邦訳すると、新しいプログラミング言語を学ぶための15のエクササイズ。この記事ではこれを解いていきます。

Rustに挑戦してみることにしました

最近注目度の高いRustにちょうど挑戦したかったので、このエクササイズにRustでチャレンジします。

第一回

Display series of numbers (1,2,3,4, 5....etc) in an infinite loop. The program should quit if someone hits a specific key (Say ESCAPE key).

解答例

さっそく私の解答から出しますと、こんな感じになりました。今回はxをエスケープ用のキーとしています。

main.rs
extern crate getch;

use getch::Getch;
use std::sync::mpsc::channel;
use std::thread::spawn;
use std::result::Result;
use std::io::Error;

fn main() {
    println!("If you want to stop, please press x key!");
    let (sender, receiver) = channel();

    spawn(move || {
        loop{
            let g: Result<Getch, Error> = Getch::new();
            let key: Result<u8, Error> = Getch::getch(&g.ok().unwrap());
            const KEY_X: u8 = 120;

            let input_key = key.ok().unwrap();
            if input_key == KEY_X {
                sender.send(true).unwrap();
                break;
            }
        }
    });
    let mut i = 0;
    loop {
        println!("{}", i);
        i = i + 1;
        if receiver.try_recv().ok() != None {
            break;
        }
    }
}

解説

インポート文

import.rs
extern crate getch;

use getch::Getch;
use std::sync::mpsc::channel;
use std::thread::spawn;
use std::result::Result;
use std::io::Error;

長い。

もう少しスマートな書き方があるのではないかと調べているけれど見つからず、と言った感じです。

今回は、keyが押されたかどうかを知るためにGetchを利用しました。

チャネル定義

channel.rs
    println!("If you want to stop, please press x key!");
    let (sender, receiver) = channel();

一文目は普通のprintlnです。止めたかったらxボタン押してねと。

二文目は、スレッド間で通信するためのチャネルを定義しています。結構雑な理解なので私は説明できる水準ではありません。

ループ部分1:キー入力を受け取る

loop1.rs
    spawn(move || {
        loop{
            let g: Result<Getch, Error> = Getch::new();
            let key: Result<u8, Error> = Getch::getch(&g.ok().unwrap());
            const KEY_X: u8 = 120;

            let input_key = key.ok().unwrap();
            if input_key == KEY_X {
                sender.send(true).unwrap();
                break;
            }
        }
    });

spawnやらmoveやらでスレッドを立てています。

Getchの処理は非常に苦労したのですが、とりあえずこれで動きます。(ベストプラクティスからは程遠いです)
Rustでは、Result型というものがあり、これがなかなか面倒くさいです。

条件を満たしたら、sender.sendでtrueを送信

ループ2

loop2.rs
    let mut i = 0;
    loop {
        println!("{}", i);
        i = i + 1;
        if receiver.try_recv().ok() != None {
            break;
        }
    }

普通にループしているだけですね。先ほどのsenderから送られた信号を受信したらループをbreakします。

まとめ

  • Rustはとても楽しい
  • Result型難しい
  • インポート文を簡潔にする方法がよくわからない。

以上!

11
7
10

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
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?