プログラミング

Rubyのように書け、Cのように速いプログラム言語 Crystal の基本的な使い方

投稿日:2018年5月31日 更新日:

Crystal というプログラミング言語の基本的な使い方について紹介します。

実際に「使ってみたい」「試してみたい」といった方に向けて、コードを書き始めるまでの導入方法について書きました。文法の説明などはしていません。

1. Crystal の概要

公式サイト The Crystal Programming Language を見ると、「Fast as C, slick as Ruby」という紹介文がついています。これが、Crystal のコンセプトのようです。

Crystal 公式サイト

ちなみに、slick という単語は形容詞として「〔物事が〕洗練された、優雅な、心地良い」という意味を持っています。Ruby の文法を指しているわけですね。

Introduction · GitBook には、このプログラミング言語の持っている目的が以下のように説明されています。

Crystal は以下の目的を持ったプログラミング言語です。

  • Rubyに似た文法を持つ(但し、Rubyと互換性を持つことが目的ではない)。
  • 静的型付け言語。型の指定は必須ではない(型推論)。
  • Crystalでバインディングを書くことで、C言語のコードを呼び出すことができる。
  • 重複したコードの記述を避けるために、コンパイル時に評価処理とコードの生成処理を行う(→ マクロのことだと思います)。
  • 効率の良いネイティブコードへコンパイルする。

おそらくこの言語がターゲットとしているのは、「今まで Ruby を使ってきたんだけど、もっと高速に動作するプログラミング言語を使いたい。静的型付けでバグの数を減らしたい。」と思っているユーザーだと思われます。Ruby とほぼ同じ文法が使えるため、乗り換えコストが非常に低いというメリットが生かせます。

GitHub のリリースページ Releases · crystal-lang/crystal · GitHub を見てみると、未だにバージョンが 1を超えていませんでした。「1 未満のバージョンは正式なリリースではないので、仕事で使うには不安だ」という考えは最近だと薄れてきているのでしょうか?

2. Crystal のインストール

今回は、Windows 10 に導入した WSL 上にインストールしてみました。

WSL の導入方法については2つ記事を書いていますので、そちらを参考にしてください。

Windows

WSL のシンプルな導入手順(2019年1月版)

2018.05.25
Windows

WSL (Windows Subsystem for Linux) の導入と設定

2017.07.12

現在の環境を確認

WSL では Ubuntu を使っています。

$ cat /etc/issue
Ubuntu 16.04.3 LTS \n \l

Crystal のインストール手順

まず、Ubuntu のパッケージ管理ツールである apt に、Crystal のレポジトリ情報と鍵を追加します。

$ curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash

/etc/apt/sources.list.d/crystal.list というファイルが追加されました。

Crystal に必要なライブラリをインストールします。

$ sudo apt-get install clang binutils

Crystal をインストールします。

$ sudo apt-get install crystal

crystalshards の2つのコマンドがインストールされました。

crystal が Crystal そのものです。

$ crystal -v
Crystal 0.24.2 [4f9ed8d03] (2018-03-08)

LLVM: 4.0.0
Default target: x86_64-unknown-linux-gnu

shards は Crystal のライブラリ依存ライブラリ管理ツールコマンドです。

$ shards --version
Shards 0.7.2 [95c6a61] (2018-03-08)

※ ここでは Crystal のドキュメント通りに、apt-get コマンドを使っていますが、Ubuntu 14.04 以降は apt コマンドを使うことが推奨されています。

3. crystal コマンドの使い方

Crystal では crystal コマンドを使うのですが、このコマンドには第一引数としてサブコマンドを与えて使います。

crystal [command]

ヘルプを表示すると、どんなサブコマンドがあるか分かります。
(引数なしで crystal コマンドを実行するとヘルプが表示されます)

$ crystal
Usage: crystal [command] [switches] [program file] [--] [arguments]

Command:
    init                     generate a new project
    build                    build an executable
    deps                     install project dependencies
    docs                     generate documentation
    env                      print Crystal environment information
    eval                     eval code from args or standard input
    play                     starts crystal playground server
    run (default)            build and run program
    spec                     build and run specs (in spec directory)
    tool                     run a tool
    help, --help, -h         show this help
    version, --version, -v   show version

「サブコマンド」というのは、私が勝手にそう読んでいるだけで、このヘルプだと「[command]」と記載されています。

「run (default)」とあるように、このサブコマンドの部分に何も指定しないと、それは run を指定したことになります。そしてこの run の説明文に「build and run program」とあるように、この場合は、ビルド処理と実行処理を両方を続けて行います。実行ファイルが生成されたりはしません。

crystal run

まずは、以下の内容を、hello.cr というファイル名で保存しておきます。

Crystal のファイル拡張子は、.cr です。

puts "Hello world!"

Ruby そのものの文法です。

※ ウェブサイトでコードを記述した場合、Ruby用のシンタックスハイライトが使えるのも地味に便利です。

そして、crystal コマンドの引数にこのファイルを指定して実行します。

$ crystal hello.cr
Hello world!

”Hello world!” と表示されましたが、これは「コンパイル」+「実行」が行われましたということです。

このコマンドを実行したからといって、実行ファイルが別途作成された様子もありません。

これは、以下のように run を指定しても同じです。

$ crystal run hello.cr

crystal build

実行ファイルを作成するには、crystal build を実行します。

先程の hello.cr ファイルをコンパイルして実行ファイルを作成してみましょう。

$ crystal build hello.cr

この操作により、hello という名前の実行ファイルが作成されたはずです。

$ ls -l
合計 1044
-rwxrwxrwx 1 root root 1065168  5月 31 13:04 hello
-rwxrwxrwx 1 root root      20  5月 31 11:57 hello.cr

この結果から分かるように、このファイルに実行権限が与えられていますので(WSL の環境ではこうなります)、このまま hello を実行してみましょう。

$ ./hello
Hello world!

“Hello world!” が出力されました。

リリース用の実行ファイルを生成する

ところで、今行ったビルド処理は最適化が行われていません。
リリース用途などで最適化したい場合は、--release オプションを指定します。

静的リンクの実行ファイルを生成する

また、オプションなしの crystal build コマンドは、「動的リンク」な実行ファイルを生成します。
もし、静的リンクにしたいのであれば、--static オプションを使いましょう。

その他のオプション

crystal build コマンドのオプションを知りたい場合は、--help オプションを付けます。

$ crystal build --help
Usage: crystal build [options] [programfile] [--] [arguments]

Options:
    --cross-compile                  cross-compile
    -d, --debug                      Add full symbolic debug info
    --no-debug                       Skip any symbolic debug info
    --lto=FLAG                       Use ThinLTO --lto=thin
    -D FLAG, --define FLAG           Define a compile-time flag
    --emit [asm|llvm-bc|llvm-ir|obj] Comma separated list of types of output for the compiler to emit
    -f text|json, --format text|json Output format text (default) or json
    --error-trace                    Show full error trace
    -h, --help                       Show this message
    --ll                             Dump ll to Crystal's cache directory
    --link-flags FLAGS               Additional flags to pass to the linker
    --mcpu CPU                       Target specific cpu type
    --mattr CPU                      Target specific features
    --no-color                       Disable colored output
    --no-codegen                     Don't do code generation
    -o                               Output filename
    --prelude                        Use given file as prelude
    --release                        Compile in release mode
    -s, --stats                      Enable statistics output
    -p, --progress                   Enable progress output
    -t, --time                       Enable execution time output
    --single-module                  Generate a single LLVM module
    --threads                        Maximum number of threads to use
    --target TRIPLE                  Target triple
    --verbose                        Display executed commands
    --static                         Link statically
    --stdin-filename                 Source file name to be read from STDIN

4. プレイグラウンド

crystal play というコマンドを使うと、ウェブサーバーが立ち上がり、Crystal のプログラミングを試すことのできるウェブページが使えるようになります。

では、実行してみましょう。

$ crystal play
Listening on http://localhost:8080

出力されたURLを見てみると、http://localhost:8080 とありますので、ウェブブラウザでこのURLにアクセスしましょう。

こんなページが表示されます。

Crystal の Playground ページ
Crystal の Playground ページ

このページ右上にあるそれぞれのメニュー別に説明します。

Playground のメニュー
Playground のメニュー

Playground

  • タイピングが止まった時、もしくは緑のボタンを押した時に、コードがコンパイルされ実行されます。
  • コードの右側には、その行の「値」と「型」が表示されます。
値と型
値と型
  • ループ処理の中の値も、表形式で全て表示することができます(こういう場合、Tuple が便利)。
ループされた値と型の表示
ループされた値と型の表示
  • puts などで出力が伴う場合は、画面下のパネルに表示されます。
Output
  • 入力したコードを Gist でシェアしたり、ファイルに保存することができます。
Gistでシェア・ファイルに保存するボタン
Gistでシェア・ファイルに保存するボタン
  • 全ての標準ライブラリが使えます。ウェブサーバーすら起動できます。
  • 分かりやすくエラーを表示してくれます。

Workbook

  • カレントディレクトリにある playground ディレクトリ内の .md, .html, .cr を一覧表示してくれる。
playgroundディレクトリ内のファイル
playgroundディレクトリ内のファイル

playgroundディレクトリにこのようなファイルがある場合、以下のような表示になります。

Worbookでの一覧表示
Worbookでの一覧表示
  • そのどれかをクリックすれば、そのファイルの内容を表示してくれます。 そのファイル内に記述したCrystal のコードを、Playgroundページのようにコンパイル&実行してくれる。
  • Jupyter Notebook に似ています。

About

  • この Playground について説明しているページです。

メニュー右端の設定アイコン

  • 設定ページです。
  • 現時点では、以下の3つが設定できました。
    1. Gist へアクセスするためのアクセストークン
    2. 「型」を表示するかどうか
    3. コードを入力した後、何秒後に自動でコンパイル&実行するか

5. ライブラリの使い方

Crystal でライブラリをどうやって使うのでしょうか?

例として Kemal を使ってみます。ライブラリの使い方だけ分かればよいので、Kemal の込み入った使い方までは説明しません。細かく知りたい方は、Kemal – Guide を読んでください。

準備作業

crystal コマンドで プロジェクトを作成します。

$ crystal init app your_app
$ cd your_app

以下のファイルとディレクトリが生成されます。

$ ls -alF
合計 4
drwxrwxrwx 0 root root 4096  5月 1 23:17 ./
drwxrwxrwx 0 root root 4096  5月 1 23:17 ../
-rwxrwxrwx 1 root root  137  5月 1 23:17 .editorconfig*
drwxrwxrwx 0 root root 4096  5月 1 23:17 .git/
-rwxrwxrwx 1 root root   29  5月 1 23:17 .gitignore*
-rwxrwxrwx 1 root root   18  5月 1 23:17 .travis.yml*
-rwxrwxrwx 1 root root 1074  5月 1 23:17 LICENSE*
-rwxrwxrwx 1 root root  611  5月 1 23:17 README.md*
-rwxrwxrwx 1 root root  151  5月 1 23:17 shard.yml*
drwxrwxrwx 0 root root 4096  5月 1 23:17 spec/
drwxrwxrwx 0 root root 4096  5月 1 23:17 src/

Kemal の導入

shard.ymlファイルに、以下を追記します。

dependencies:
  kemal:
    github: kemalcr/kemal

これは依存ライブラリとして、Kemal を登録しています。

次に、shards コマンドを実行して依存ライブラリをダウンロードします。

$ shards install

もしくは

$ crystal deps install

crystal deps は、shards を呼び出しているだけのようです。

これでライブラリの導入は完了です。

では、ライブラリを使ったコードを書いてみます。

src/your_app.cr ファイルに以下を記述してください。

require "kemal"

get "/" do
  "Hello World!"
end

Kemal.run
1行目
require "kemal" という部分で、導入したライブラリを読み込んでいます。
3行目
“/” というパスと、do "Hello World!" end というブロックを引数にして、get メソッドを実行しています。これにより、「ウェブブラウザで、このウェブサイトの一番上のパス(URL)に対して、GETメソッドでアクセスしてきた場合に、”Hello World!” という文字列を返す」という動作を登録しています。
7行目
Kemal.run によって、ウェブサーバーをスタートしています。

実行してみましょう。

$ crystal run src/your_app.cr
[development] Kemal is ready to lead at http://0.0.0.0:3000
2018-05-01 23:35:30 +09:00 200 GET / 4.08ms
2018-05-01 23:35:30 +09:00 404 GET /favicon.ico 34.1ms
2018-05-01 23:35:30 +09:00 404 GET /favicon.ico 237.0µs

この出力の中で、http://0.0.0.0:3000 とあるように 3000番ポートでウェブサーバーが起動したことが分かります。

ウェブブラウザで、http://localhost:3000 にアクセスしてみましょう。

正常にウェブページが表示されました。
正常にウェブページが表示されました。

ちゃんと、”Hello World!” と表示されました。

ここまでの手順で、プロジェクト内でライブラリを導入する方法は分かりました。

6. おわりに

Ruby の文法をそのままに、「更に速く」「静的型付けで安全に」といった願望を叶えてくれるプログラミング言語です。一定の需要がある言語だと思いますが、その割に広まってないような気がします。ちょっとしたツールを作るにも際にも、Rubyの代わりとして使えますね。個人的にも流行って欲しいプログラミング言語です。



📂-プログラミング
-

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Python

Pythonのバージョンを切り替える pyenv の使い方

Pythonのバージョンを切り替える pyenv の使い方について説明します。

Web Programming

ソフトウェアにおける日付・時刻フォーマット

目次ソフトウェアにおける日付・時刻フォーマット参考情報ISO 8601RFC 5322RFC 7231Common Log Format ソフトウェアにおける日付・時刻フォーマット ソフトウェア(特に …

Web Components

Web Components のサンプルコード

Web Components を使ったサンプルコードを紹介します。

Web

OpenID Connect の処理フロー

OpenID Connect の処理フローを図にしました。

Canvasでの回転

Canvas に回転した画像を表示するサンプルページを作りました

Canvas に回転した画像を表示するサンプルページを作りました。 Canvas の標準の機能では用意されていない操作なので、自分でこの処理を書く場合は少々面倒な記述が必要になります。 目次1. スク …