Crystal言語を使ってみる(インストール編)

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

私がよく使ってた..言語にRubyというのがありまして、文法がわかりやすくてインタプリターでログの集計とかによく使っていました。
しかし、実行速度があまり早くないのでRubyをコンパイルとかできないのかなと調べて、
ruby-packerやTruffleRubyってのをみつけました。
しかし、今ひとつしっくりこないなぁと悶々とする日々でした。
とあるRuby系ニュースメールにCrystalって言語があるというのを知ったのでWindows Subsystem for LinuxのUbuntu 20.04にインストールしてみました。

プログラミング言語 Crystal 
https://ja.crystal-lang.org/

日本語でのCrystal言語についての資料は以下のPDFがよいと思います。

[Introducing Crystal Programming Language](https://crystal-jp.github.io/introducing-crystal/assets/pdfs/introducing-crystal.pdf)

# 1. インストール方法を調べる

https://ja.crystal-lang.org/install/

Ubuntuだと以下の方法でインストールできそうです。

```
curl -fsSL https://crystal-lang.org/install.sh | sudo bash
```

[Ubuntu へのインストール](https://ja.crystal-lang.org/install/on_ubuntu/)

※Snapcraft や Linuxbrew でもインストールできそうです。

# 2. やってみる
## 2-1. Windows Subsystem for Linuxへインストール

```bash
curl -fsSL https://crystal-lang.org/install.sh | sudo bash
```

<details>
<summary>インストールログ</summary>
$ curl -fsSL https://crystal-lang.org/install.sh | sudo bash
Get:1 https://packages.cloud.google.com/apt cloud-sdk InRelease [6739 B]
Hit:2 http://archive.ubuntu.com/ubuntu focal InRelease
Get:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Fetched 335 kB in 2s (136 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
wget is already the newest version (1.20.3-1ubuntu1).
wget set to manually installed.
gpg is already the newest version (2.2.19-3ubuntu2.1).
gpg set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
deb http://download.opensuse.org/repositories/devel:languages:crystal/xUbuntu_20.04/ /
Hit:1 https://packages.cloud.google.com/apt cloud-sdk InRelease
0% [Connecting to archive.ubuntu.com] [Connecting to security.ubuntu.com] [Connecting to download.opensuse.org (195.13Get:3 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Hit:4 http://archive.ubuntu.com/ubuntu focal InRelease
Get:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:2 http://download.opensuse.org/repositories/devel:languages:crystal/xUbuntu_20.04  InRelease [1538 B]
Get:6 http://download.opensuse.org/repositories/devel:languages:crystal/xUbuntu_20.04  Packages [1920 B]
Get:7 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Fetched 332 kB in 2s (137 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  icu-devtools libevent-core-2.1-7 libevent-dev libevent-extra-2.1-7 libevent-openssl-2.1-7
  libevent-pthreads-2.1-7 libgmp-dev libgmpxx4ldbl libicu-dev libpcre16-3 libpcre3-dev
  libpcre32-3 libpcrecpp0v5 libxml2-dev libyaml-dev pkg-config
Suggested packages:
  gmp-doc libgmp10-doc libmpfr-dev icu-doc libyaml-doc
The following NEW packages will be installed:
  crystal icu-devtools libevent-core-2.1-7 libevent-dev libevent-extra-2.1-7
  libevent-openssl-2.1-7 libevent-pthreads-2.1-7 libgmp-dev libgmpxx4ldbl libicu-dev
  libpcre16-3 libpcre3-dev libpcre32-3 libpcrecpp0v5 libxml2-dev libyaml-dev pkg-config
0 upgraded, 17 newly installed, 0 to remove and 0 not upgraded.
Need to get 30.8 MB of archives.
After this operation, 147 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu focal/main amd64 icu-devtools amd64 66.1-2ubuntu2 [188 kB]
Get:2 http://download.opensuse.org/repositories/devel:languages:crystal/xUbuntu_20.04  crystal 1.2.1-1+1.1 [18.7 MB]
Get:3 http://archive.ubuntu.com/ubuntu focal/main amd64 libevent-core-2.1-7 amd64 2.1.11-stable-1 [89.1 kB]
Get:4 http://archive.ubuntu.com/ubuntu focal/main amd64 libevent-extra-2.1-7 amd64 2.1.11-stable-1 [60.0 kB]
Get:5 http://archive.ubuntu.com/ubuntu focal/main amd64 libevent-pthreads-2.1-7 amd64 2.1.11-stable-1 [7372 B]
Get:6 http://archive.ubuntu.com/ubuntu focal/main amd64 libevent-openssl-2.1-7 amd64 2.1.11-stable-1 [14.3 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal/main amd64 libevent-dev amd64 2.1.11-stable-1 [261 kB]
Get:8 http://archive.ubuntu.com/ubuntu focal/main amd64 libgmpxx4ldbl amd64 2:6.2.0+dfsg-4 [9128 B]
Get:9 http://archive.ubuntu.com/ubuntu focal/main amd64 libgmp-dev amd64 2:6.2.0+dfsg-4 [320 kB]
Get:10 http://archive.ubuntu.com/ubuntu focal/main amd64 libicu-dev amd64 66.1-2ubuntu2 [9450 kB]
Get:11 http://archive.ubuntu.com/ubuntu focal/main amd64 libpcre16-3 amd64 2:8.39-12build1 [150 kB]
Get:12 http://archive.ubuntu.com/ubuntu focal/main amd64 libpcre32-3 amd64 2:8.39-12build1 [140 kB]
Get:13 http://archive.ubuntu.com/ubuntu focal/main amd64 libpcrecpp0v5 amd64 2:8.39-12build1 [15.5 kB]
Get:14 http://archive.ubuntu.com/ubuntu focal/main amd64 libpcre3-dev amd64 2:8.39-12build1 [540 kB]
Get:15 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 libxml2-dev amd64 2.9.10+dfsg-5ubuntu0.20.04.1 [735 kB]
Get:16 http://archive.ubuntu.com/ubuntu focal/main amd64 pkg-config amd64 0.29.1-0ubuntu4 [45.5 kB]
Get:17 http://archive.ubuntu.com/ubuntu focal/main amd64 libyaml-dev amd64 0.2.2-1 [58.2 kB]
Fetched 30.8 MB in 13s (2388 kB/s)
Selecting previously unselected package icu-devtools.
(Reading database ... 83502 files and directories currently installed.)
Preparing to unpack .../00-icu-devtools_66.1-2ubuntu2_amd64.deb ...
Unpacking icu-devtools (66.1-2ubuntu2) ...
Selecting previously unselected package libevent-core-2.1-7:amd64.
Preparing to unpack .../01-libevent-core-2.1-7_2.1.11-stable-1_amd64.deb ...
Unpacking libevent-core-2.1-7:amd64 (2.1.11-stable-1) ...
Selecting previously unselected package libevent-extra-2.1-7:amd64.
Preparing to unpack .../02-libevent-extra-2.1-7_2.1.11-stable-1_amd64.deb ...
Unpacking libevent-extra-2.1-7:amd64 (2.1.11-stable-1) ...
Selecting previously unselected package libevent-pthreads-2.1-7:amd64.
Preparing to unpack .../03-libevent-pthreads-2.1-7_2.1.11-stable-1_amd64.deb ...
Unpacking libevent-pthreads-2.1-7:amd64 (2.1.11-stable-1) ...
Selecting previously unselected package libevent-openssl-2.1-7:amd64.
Preparing to unpack .../04-libevent-openssl-2.1-7_2.1.11-stable-1_amd64.deb ...
Unpacking libevent-openssl-2.1-7:amd64 (2.1.11-stable-1) ...
Selecting previously unselected package libevent-dev.
Preparing to unpack .../05-libevent-dev_2.1.11-stable-1_amd64.deb ...
Unpacking libevent-dev (2.1.11-stable-1) ...
Selecting previously unselected package libgmpxx4ldbl:amd64.
Preparing to unpack .../06-libgmpxx4ldbl_2%3a6.2.0+dfsg-4_amd64.deb ...
Unpacking libgmpxx4ldbl:amd64 (2:6.2.0+dfsg-4) ...
Selecting previously unselected package libgmp-dev:amd64.
Preparing to unpack .../07-libgmp-dev_2%3a6.2.0+dfsg-4_amd64.deb ...
Unpacking libgmp-dev:amd64 (2:6.2.0+dfsg-4) ...
Selecting previously unselected package libicu-dev:amd64.
Preparing to unpack .../08-libicu-dev_66.1-2ubuntu2_amd64.deb ...
Unpacking libicu-dev:amd64 (66.1-2ubuntu2) ...
Selecting previously unselected package libpcre16-3:amd64.
Preparing to unpack .../09-libpcre16-3_2%3a8.39-12build1_amd64.deb ...
Unpacking libpcre16-3:amd64 (2:8.39-12build1) ...
Selecting previously unselected package libpcre32-3:amd64.
Preparing to unpack .../10-libpcre32-3_2%3a8.39-12build1_amd64.deb ...
Unpacking libpcre32-3:amd64 (2:8.39-12build1) ...
Selecting previously unselected package libpcrecpp0v5:amd64.
Preparing to unpack .../11-libpcrecpp0v5_2%3a8.39-12build1_amd64.deb ...
Unpacking libpcrecpp0v5:amd64 (2:8.39-12build1) ...
Selecting previously unselected package libpcre3-dev:amd64.
Preparing to unpack .../12-libpcre3-dev_2%3a8.39-12build1_amd64.deb ...
Unpacking libpcre3-dev:amd64 (2:8.39-12build1) ...
Selecting previously unselected package libxml2-dev:amd64.
Preparing to unpack .../13-libxml2-dev_2.9.10+dfsg-5ubuntu0.20.04.1_amd64.deb ...
Unpacking libxml2-dev:amd64 (2.9.10+dfsg-5ubuntu0.20.04.1) ...
Selecting previously unselected package pkg-config.
Preparing to unpack .../14-pkg-config_0.29.1-0ubuntu4_amd64.deb ...
Unpacking pkg-config (0.29.1-0ubuntu4) ...
Selecting previously unselected package crystal.
Preparing to unpack .../15-crystal_1.2.1-1+1.1_amd64.deb ...
Unpacking crystal (1.2.1-1+1.1) ...
Selecting previously unselected package libyaml-dev:amd64.
Preparing to unpack .../16-libyaml-dev_0.2.2-1_amd64.deb ...
Unpacking libyaml-dev:amd64 (0.2.2-1) ...
Setting up libpcrecpp0v5:amd64 (2:8.39-12build1) ...
Setting up libpcre16-3:amd64 (2:8.39-12build1) ...
Setting up libyaml-dev:amd64 (0.2.2-1) ...
Setting up libgmpxx4ldbl:amd64 (2:6.2.0+dfsg-4) ...
Setting up libpcre32-3:amd64 (2:8.39-12build1) ...
Setting up libevent-core-2.1-7:amd64 (2.1.11-stable-1) ...
Setting up icu-devtools (66.1-2ubuntu2) ...
Setting up pkg-config (0.29.1-0ubuntu4) ...
Setting up libicu-dev:amd64 (66.1-2ubuntu2) ...
Setting up libevent-pthreads-2.1-7:amd64 (2.1.11-stable-1) ...
Setting up libevent-extra-2.1-7:amd64 (2.1.11-stable-1) ...
Setting up libgmp-dev:amd64 (2:6.2.0+dfsg-4) ...
Setting up libpcre3-dev:amd64 (2:8.39-12build1) ...
Setting up libevent-openssl-2.1-7:amd64 (2.1.11-stable-1) ...
Setting up libxml2-dev:amd64 (2.9.10+dfsg-5ubuntu0.20.04.1) ...
Setting up libevent-dev (2.1.11-stable-1) ...
Setting up crystal (1.2.1-1+1.1) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
</details>

問題なくインストールできました。

# 3. 動作確認
## 3-1. バージョン表示

```bash
$ crystal --version
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/88744c69-c367-1e20-fca0-23eea97e28ef.png)

バージョン 1.2.1がインストールされています。

## 3-2. おきまりのHello World

`hello_world.cr`ファイルを作成

```crystal:hello_world.cr
puts "Hello World!"
```

このファイルを実行します

```bash
$ crystal hello_world.cr
```

実行結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/9753bef7-dd6b-340c-c261-4c208fd291be.png)

インタプリターみたいにコンパイルすることなく実行されました。

## 3-3. インタプリター実行の実行時間

timeで実行時間を計測してみます。

```bash
$ time crystal hello_world.cr
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/637eb877-4128-f5e1-52eb-59a01bd17599.png)

## 3-4. コンパイル実行の実行時間

コンパイルしながら実行してみます。

```bash
$ crystal run hello_world.cr
```

当然ながら、インタプリター実行と同じぐらいの時間になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/b68da734-000b-5f10-17b1-a08e519703e5.png)

## 3-5. コンパイルしてから実行

つぎは、コンパイル後に実行したときの時間を計測してみます。

まず、ビルドします。

```bash
$ crystal build hello_world.cr
```

ビルドできたので実行します。

```bash
time ./hello_world
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/6d99a264-0fb8-534d-e0e2-5999e5d75fc5.png)

ぐっと早くなりますね！

## 3-6. リリースビルドしてから実行

`--release`を付けるとさらに最適化されるそうです。
やってみます。

```bash
$ crystal build hello_world.cr --release
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/5c640842-0558-967c-3588-2c97923d497e.png)

コードが小さいので、あれですが実行時間は半分ですね。

# 4. まとめ

Rubyに似た文法をもつCrystal言語を試してみました。
WSL上で使えるので各種ファイルの操作に使えて便利そうです。

インタプリター的に使えるコンパイラー言語はいくつかありますが、Crystalは手軽に使えそうなので今後試していきたいと思います。