GoとRustの比較
こういうバージョンの処理系で試した。
$ go version go version go1.1.2 linux/amd64 $ rustc --version rustc 0.9-pre (825b127 2013-11-12 18:56:13 -0800) host: x86_64-unknown-linux-gnu
// Go package main import ( "fmt" "sort" "strconv" ) type T struct { int string } type U []*T func (s U) Len() int { return len(s) } func (s U) Less(i, j int) bool { return s[i].int < s[j].int } func (s U) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func main() { ch := make(chan *T) for i := 0; i < 100; i++ { go func(i int) { var b string switch x, y := i%3, i%5; true { case x == 0 && y == 0: b = "FizzBuzz" case x == 0 && y != 0: b = "Fizz" case x != 0 && y == 0: b = "Buzz" default: b = strconv.Itoa(i) } ch <- &T{i, b} }(i + 1) } res := make(U, 0, 100) for i := 0; i < 100; i++ { res = append(res, <-ch) } sort.Sort(res) for _, v := range res { fmt.Println(v.string) } }
// Rust 0.9-pre extern mod extra; fn main() { let (port, chan) = stream(); let chan = std::comm::SharedChan::new(chan); for i in range(0, 100) { let chan = chan.clone(); do spawn { let i = i + 1; let b = match (i % 3, i % 5) { (0, 0) => ~"FizzBuzz", (0, _) => ~"Fizz", (_, 0) => ~"Buzz", _ => i.to_str() }; chan.send((i, b)); } } let mut res = ~[]; do 100.times { res.push(port.recv()); } extra::sort::quick_sort(res, |t, u| t.first() <= u.first()); for t in res.iter() { std::io::println(t.second()); } }
Goはダックタイピングでゆるふわ系で、Rustは厳密に型付けして型推論バリバリ系。
Rustの側はデータの受け取りをタプルで済ませていたり、比較用関数はラムダ式で渡せば良かったりするので短くなっている。Goはtypeで雑多な型を宣言した上で、雑多な型に対してSort用のメソッド定義している。面倒臭い。
Rustのmatchは式なんだけど、Goのswitchは文なので、変数bの宣言を前に出すはめになってしまい、無駄に型を書くことになった。
forループの変数のスコープ、Goの場合はループ全体で同じ変数なので、go文に渡す関数の引数を介してやらないと正しく動きません。Rustはループ毎に別なのでそのまま使って大丈夫。
ビルド時間はGoのが断然はやい。
$ time go build fizzbuzz.go real 0m0.185s user 0m0.146s sys 0m0.038s $ time rustc fizzbuzz_0.9.rs real 0m1.215s user 0m1.092s sys 0m0.119s
バイナリの実行速度は、このコードで比較するのはやめておきます……