最近やや盛り上がりつつあるRustを使ってみることにしました。
試しに、RustとパッケージマネージャCargoを導入してから、Fizz-Buzzを書いてみました。
RustとCargoの導入
Rustの導入
Rustは古いバージョンだと上手く動かなかったりするのでNightlyバージョンを導入しましょう。
Homebrewだとちょっと古いバージョンになるので、今回は公式ページからMac binaries (.tar.gz) の64-bit版をダウンロードしました。
インストールにはこれを解凍してinstall.shを実行するだけです。
$ tar zxvf ~/Downloads/rust-nightly-x86_64-apple-darwin.tar.gz $ cd rust-nightly-x86_64-apple-darwin $ ./install.sh
これで、/usr/localあたりにrustcがインストールされます。あとは、/usr/local/binにパスを通せばよいです。
$ rustc --version rustc 0.12.0-pre-nightly (2e3858179 2014-09-03 00:51:00 +0000)
Cargo
パッケージマネージャのCargoはGitHubページのリンクからx86_64-apple-darwinをダウンロードして、その中のファイルcargoを/usr/local/binに置きました。
$ cargo version cargo 0.0.1-pre-nightly (3139954 2014-09-03 05:22:14 +0000)
新規プロジェクトの作成
CargoでRustの新規プロジェクトを作成するにはcargo newします。
$ cargo new --bin --git fizzbuzz
プロジェクト用ディレクトリfizzbuzzが生成されます。
$ cd fizzbuzz $ ls -a ./ ../ .git/ .gitignore Cargo.toml src/ $ ls src main.rs
--binを付けたのでバイナリ向けのテンプレートが生成されており、--gitを付けたので.gitと.gitignoreが生成されています。
ファイルはトラックされていないので、すぐにcommitしてしまってもよいでしょう。
cargo用の設定ファイルCargo.tomlはこんな感じ。今回は何も手を入れずに利用しています。
$ cat Cargo.toml [package] name = "fizzbuzz" version = "0.0.1" authors = ["Safx <safxdev@example.com>"]
ちなみにcargoを引数なしで実行するとこんな感じになります。
$ cargo Rust's package manager Usage: cargo <command> [<args>...] cargo [options] Options: -h, --help Display this message -V, --version Print version info and exit --list List installed commands -v, --verbose Use verbose output Some common cargo commands are: build Compile the current project clean Remove the target directory doc Build this project's and its dependencies' documentation new Create a new cargo project run Build and execute src/main.rs test Run the tests bench Run the benchmarks update Update dependencies listed in Cargo.lock See 'cargo help <command>' for more information on a specific command.
試しにコンパイル
cargo newで生成されたソースファイルはこんな感じです。
$ cat src/main.rs
fn main() {
    println!("Hello, world!")
}
とりあえずコンパイルしてみます。これにはcargo buildするだけです。
$ cargo build Compiling fizzbuzz v0.0.1 (file:///Users/safx/src/fizzbuzz)
これで、targetというディレクトリが生成されて、その中にfizzbuzzというバイナリが生成されます。
$ ./target/fizzbuzz Hello, world!
テストを書く
テストファーストでFizz-Buzzを書いていきますので、テストとfizzbuzzの空実装を書きます。
fn fizzbuzz(n: int) -> String {
   "".to_string()
}
#[test]
fn test_fizz() {
    assert_eq!(fizzbuzz(3), "fizz".to_string())
    assert_eq!(fizzbuzz(6), "fizz".to_string())
    assert_eq!(fizzbuzz(9), "fizz".to_string())
}
Rustでは#[test]がある関数はテストケースとしてテスト時に実行されます。テストを実行してみましょう。
$ cargo test
   Compiling fizzbuzz v0.0.1 (file:///Users/safx/src/fizzbuzz)
/Users/safx/src/fizzbuzz/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
/Users/safx/src/fizzbuzz/src/main.rs:1 fn main() {
/Users/safx/src/fizzbuzz/src/main.rs:2     println!("Hello, world!")
/Users/safx/src/fizzbuzz/src/main.rs:3 }
/Users/safx/src/fizzbuzz/src/main.rs:5:14: 5:15 warning: unused variable: `n`, #[warn(unused_variable)] on by default
/Users/safx/src/fizzbuzz/src/main.rs:5 fn fizzbuzz(n: int) -> String {
                                                    ^
     Running target/fizzbuzz-c2448ebfc140711f
running 1 test
test test_fizz ... FAILED
failures:
---- test_fizz stdout ----
    task 'test_fizz' failed at 'assertion failed: `(left == right) && (right == left)` (left: ``, right: `fizz`)', /Users/safx/src/fizzbuzz/src/main.rs:11
failures:
    test_fizz
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
このテストを通すようにします。
fn fizzbuzz(n: int) -> String {
    if n % 3 == 0 {
        "fizz".to_string()
    } else {
       "".to_string()
    }
}
これでテストが通るようになりました。
$ cargo test
   Compiling fizzbuzz v0.0.1 (file:///Users/safx/src/fizzbuzz)
/Users/safx/src/fizzbuzz/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
/Users/safx/src/fizzbuzz/src/main.rs:1 fn main() {
/Users/safx/src/fizzbuzz/src/main.rs:2     println!("Hello, world!")
/Users/safx/src/fizzbuzz/src/main.rs:3 }
     Running target/fizzbuzz-c2448ebfc140711f
running 1 test
test test_fizz ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
実装
そんなこんなで完成したFizz-Buzzがこちら。
fn main() {
    for i in range(1, 31) {
        println!("{}", fizzbuzz(i))
    }
}
fn fizzbuzz(n: int) -> String {
    if n % 15 == 0 {
        "fizzbuzz".to_string()
    } else if n % 3 == 0 {
        "fizz".to_string()
    } else if n % 5 == 0 {
        "buzz".to_string()
    } else {
        n.to_string()
    }
}
#[test]
fn test_num() {
    assert_eq!(fizzbuzz(1), "1".to_string())
    assert_eq!(fizzbuzz(2), "2".to_string())
    assert_eq!(fizzbuzz(4), "4".to_string())
    assert_eq!(fizzbuzz(29), "29".to_string())
}
#[test]
fn test_fizz() {
    assert_eq!(fizzbuzz(3), "fizz".to_string())
    assert_eq!(fizzbuzz(6), "fizz".to_string())
    assert_eq!(fizzbuzz(9), "fizz".to_string())
}
#[test]
fn test_buzz() {
    assert_eq!(fizzbuzz(5),  "buzz".to_string())
    assert_eq!(fizzbuzz(10), "buzz".to_string())
    assert_eq!(fizzbuzz(20), "buzz".to_string())
}
#[test]
fn test_fizzbuzz() {
    assert_eq!(fizzbuzz(15), "fizzbuzz".to_string())
    assert_eq!(fizzbuzz(30), "fizzbuzz".to_string())
}
ちなみに、cargo runで実行できます。コンパイルはそれなりに早いので割と気軽に実行できます。Goみたいですね。
$ cargo run
   Compiling fizzbuzz v0.0.1 (file:///Users/safx/src/fizzbuzz)
     Running `target/fizzbuzz`
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz
fizz
22
23
fizz
buzz
26
fizz
28
29
fizzbuzz

0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。