Crystal Advent Calendar 2015 にトルコの Rubyist である Serdar Dogruyol (@sdogruyol) が記事を投稿してくれました。せっかく日本のコミュニティの Advent Calendar に向けて書いてくれたので、日本語に翻訳したものを公開したいと思います。
原文はこちら。Why Crystal?
Why Crystal?
この記事はプログラミング言語に関する個人的な意見を書いたものです。
まず、私は Rubyist です。私は、Ruby コミュニティや Ruby の生産性、そして他にも Ruby が持つ様々な素晴らしさを心から愛しています。実際に、ここ4年以上の間、私は Ruby のコードを書くことで収入を得てきました。本当はこのままずっと Ruby を書き続けていたいのですが、言語やツールというものはいつか入れ替わる運命にあることも理解しています。
2015年、「Ruby から X に移行する方法」といった見出しのブログ記事を多く目にしたことでしょう。これは人々がより優れた代替物を求めていることの生きた証拠に他なりません。しかし、このことを単純に「Ruby は良くない」と受け取ってはいけません。そうではなく、その「X」とは何であるか、という点に注意を向けることが大切だと思っています。
ほとんどの場合、「X」に挙げられているのは Go/Rust/Elixir などです。しかし、私がここで主張したいことは、Rubyist にとってその「X」は、Crystal 以外には考えられない、ということです。
例えば、あなたが私にこう聞いたとします。
「ねぇ Serdar、なぜ Crystal を選ぶべきなの? (Why Crystal?)」
すると、きっとこう答えるでしょう。
「新しい言語を学ぶのには何日もかかります。でも、十分に熟練し生産的に使えるようになるには、何日どころではなく何年もかかるからです。」
以下の点で、Crystal は 90% Ruby だと言ってよいと考えています。
- 同様のシンタックスを持つ
- 同じイディオムを使える
更に、
- コンパイル言語
- ネイティブコード
- 非常に優れたパフォーマンス
などの特徴を持ちます。
Enter Crystal
まず例を見てみましょう。
fib.rb
def fibonacci(n)
return n if n <= 1
fibonacci(n - 1) + fibonacci(n - 2)
end
puts fibonacci 40
これはフィボナッチ数 (メモ化なし) を Crystal で記述したものです。ファイルの拡張子が「.rb」になっていることに気付いたでしょうか?そう、これは同時に Ruby のコードでもあります!
では、これを Ruby と Crystal で動かしてみましょう。
$ ruby fib.rb
102334155
$ crystal fib.rb
102334155
うん、いいですね。それではこの処理にかかった時間を見てみましょう。
Ruby
$ time ruby fib.rb
ruby fib.rb 16.62s user 0.08s system 99% cpu 16.805 total
Crystal
$ time crystal fib.rb
crystal fib.rb 0.85s user 0.18s system 118% cpu 0.870 total
Wow! これは素晴しい。実際には特に何もやっていないにも関らず、20倍のパフォーマンスを出すことができています。
でも、待ってください。LLVM の最適化を有効にするとどうなるでしょうか。
$ crystal build --release fib.rb
$ time ./fib
./fib 0.67s user 0.00s system 99% cpu 0.678 total
ネイティブコードやばい。上記では、LLVM の最適化を有効にして Crystal のプログラムをビルドして、生成されたネイティブコードを実行しました。このとき、./fib
は Ruby より25倍も速くなっています。
これはごく簡単なデモンストレーションですが、「X」が Crystal であるべき大きな理由の1つです。
Web の開発者としては、この優れたパフォーマンスによって、Sinatra のような Web アプリケーションフレームワークがどれほど恩恵を受けられるか、ということに非常に興味が湧きました。そして作ったのが Kemal です。
Enter Kemal
Crystal の真のポテンシャルを知るため、そして、実際に有用なものを作るためには、Sinatra のようなものが相応しいという考えから Kemal は生まれました。
Sinatra と全く同じシンプルな記法で書くことができます。
require "kemal"
get "/" do
"Hello World!"
end
ただ、パフォーマンスには大きな違いがあります。
$ wrk -c 100 -d 20 http://localhost:3000
- Kemal (Production) - 64986 リクエスト/秒、平均 170μs
- Sinatra (Thin) - 2274 リクエスト/秒、平均 43.82ms
Kemal は現在まだ開発中で、完全な機能は実装されていませんが、すでに以下を備えています。
- すべての REST verb をサポート
- リクエスト/レスポンスのコンテキストによる容易なパラメータの扱い
- ミドルウェア
- JSON サポートをビルトイン
- 静的ファイルサーブ機能をビルトイン
ecr
によるビューテンプレートをビルトイン
Kemal でどういったものが構築できるのかを知りたければ、Kamber をチェックしてみるのが良いでしょう。
現在の状況
Crystal は alpha のステータスで、最新の stable バージョンは 0.9.1 です。
ほとんどの標準ライブラリは完成しており、かつ安定しています。まだ production-ready とは言えませんが、Crystal を使い始めることは今すぐに可能です。
そして、私が Crystal の素晴しい点だと感じることの1つに、Crystal が Crystal 自身で書かれていることが挙げられます。それによって、Crystal のソースコードを読み、pull request/issue を介して貢献することへの敷居が低くなっています。
コミュニティ
Crystal のコミュニティは MINASWAN をルーツに持っていて、とても nice なものです。現在、IRC チャンネル (freenode の #crystal-lang) とメーリングリストが用意されています。
おわりに
ここまで読んでくれた人、貴重な時間をありがとうございます。皆さんが Crystal を楽しんでくれることを心より願っています。もし私に何か質問があれば、@sdogruyol 宛にお知らせください。
Happy Crystaling <3
P.S: ここで、Crystal の開発資金を援助することができます。