Blank File

LinuxとかPythonとかVimとか、趣味でいじる感じで

今さらRust試してみた(ついでにGo言語と少し比較)

Rustを学びシステムレベル言語を理解すること - ワザノバ | wazanova に触発されてRustを試してみました。

※ 以下の内容は全て個人の感想です。

Rust (プログラミング言語) - Wikipedia)

Mozilla謹製・・・若干不安です

インストール

OSはUbuntuです。 公式サイトのInstallからLinux用バイナリをダウンロードします。

薄い小さな字で申し訳なさそうに書いてある

Recommended Version:
nightly (Linux binary)

がアツいですね。

f:id:h-miyako:20141010163621p:plain

ダウンロードしたファイルを適当に展開します。展開したフォルダ内で

sudo ./install.sh

すればインストールされます。rustc -vでバージョンが表示されればOKです。

アンインストールは同じフォルダでsudo ./install.sh --uninstallです。非常に親切ですね。

Vimの設定

.vimrcに

NeoBundle 'wting/rust.vim'

を書いて:NeoBundleinstallするだけです。

Hello world

やっぱり最初は"Hello, world!"ですよね!公式のガイドもインストールの次は2 Hello, world! - The Rust Guideです。

vimで写経します。

fn main() {
    println!("Hello, world!");
}

おもむろにvim-quickrunで走らせたらちゃんと Hello, world! が表示されました。quickrunすごい

このコードを見るとfnが関数定義でmainが実行される関数で()が引数(今回はなし)で{...}が関数の処理でprintln関数で標準出力に出して文字列はダブルクォーテーションで行末にはセミコロンなんだな、理解しやすそうな構b・・・!って何っ!?

以下、引用です。

The second point is the println!() part. This is calling a Rust macro, which is how metaprogramming is done in Rust. If it were a function instead, it would look like this: println(). For our purposes, we don't need to worry about this difference. Just know that sometimes, you'll see a !, and that means that you're calling a macro instead of a normal function. Rust implements println! as a macro rather than a function for good reasons, but that's a very advanced topic. You'll learn more when we talk about macros later. One last thing to mention: Rust's macros are significantly different than C macros, if you've used those. Don't be scared of using macros. We'll get to the details eventually, you'll just have to trust us for now.

macro・・・だと・・・

とりあえず今は気にしなくていいらしいので、おもむろに!をとってコンパイルしたらエラーになりました

ループ

コンパイルしてるし速いんだろうな、と思って適当にループ書いて今流行りのGo言語と比較してみました。

[2015年1月23日 追記]
Rust 1.0.0αが出たので、他の言語も含めて、もう少し真面目に比較しました。

この頃 流行りの 言語たち(他)でベンチマーク (Dart, Go, Julia, Nim, Python, Rust 他) - Blank File

[追記終わり]

Rustのコード
fn main() {
    let mut sum = 0u;
    for x in range(0u, 1000000000) {
        sum = sum + x;
    }
    println!("The value of sum is: {}", sum);
}
Goのコード
package main

import (
    "fmt"
)

func main() {
    sum := 0
    for i := 0; i < 1000000000; i++ {
        sum = sum + i
    }
    fmt.Println("The value of sum is: ", sum)
}
Rustの実行結果
$ rustc hello.rs
$ time ./hello
The value of sum is: 499999999500000000
./hello  14.12s user 0.00s system 96% cpu 14.656 total
Goの実行結果
$ go build hello.go
$ time ./hello
The value of sum is:  499999999500000000
./hello  0.70s user 0.00s system 99% cpu 0.708 total

Rustの惨敗です。Rustは配列のメモリ確保に時間かかってるのかと思い、もう少しGoに近いコードに書き換えました。

Rustのコード(修正版)
fn main() {
    let mut sum = 0u;
    let mut x = 0u;
    while x < 1000000000 {
        sum = sum + x;
        x += 1u;
    }
    println!("The value of sum is: {}", sum);
}
Rust(修正版)の実行結果
$ rustc hello.rs
$ time ./hello
The value of sum is: 499999999500000000
./hello  2.14s user 0.00s system 99% cpu 2.150 total

速くなりましたがまだGoの3倍くらい時間かかってます。

単純なコードなので、書き方で簡単に数倍くらい変わりそうな気もします。 なのであまり厳密に比較することに意味はありませんし、そもそもRustは version 1.0 になっていないのでこのくらいで(飽きた

2015年1月7日 追記

コンパイル時に最適化オプションを追加したら爆速になりました。 未確認ですがコンパイル時に計算終わってますねこれ。

$ rustc --opt-level 1 hello.rs
$ time ./hello
The value of sum is: 499999999500000000
./hello  0.00s user 0.00s system 83% cpu 0.002 total

感想

Go言語いいですね!行末セミコロン不要というだけで書きやすさがかなり違います。構文もちょっと見ただけだと型定義とか違和感ありましたが、実際書いてみるとそんなに奇抜でもなく、型推論がいい感じにやってくれていい感じです。さらにコンパイルも実行も速いです。これは流行るの納得です。