多言語 Hello, World! on asdf and Docker

## はじめに

日常業務だと、どうしても同じ言語ばかり使うことになってしまいがち

しかし、新しい言語を学んでおくことは将来への投資になります

多くの言語を扱えることのメリット

- 要求機能、並列性、耐障害性、メモリ効率、開発規模などに応じて、適切な言語を選択できる
- 色々な言語の特性やメリットを他言語の開発にも活かせる
- 様々なOSSなどのコードを読めるようになる
- 自分の担当領域以外のコードも理解でき、トラブルシューティングに強くなる

フロントエンドの開発をしていて、APIの挙動で「あれ？」と思ったとき、ちらっとバックエンド側のコードを見てバグを指摘したりできるのは強いです（逆もまた然り）

というわけで、色々な言語の開発環境をざっくり作るためのリポジトリーを作りました

ついでに分岐やループの例も書いておきました

時間のあるときにコンテンツを充実させていこうと思います

https://github.com/RyoWakabayashi/hello-worlds

現時点で実装した言語は以下の通り

- [Dart]
- [elixir]
- [elm]
- [Go][golang]
- [Java]
- [Kotlin]
- [Markdown]
- [Node.js][nodejs]
- [PHP]
- [Python]
- [R]
- [Ruby]
- [Rust]
- [Scala]
- [Shell Script][shell]
- [Swift] Ubuntu 上での asdf swift が上手く動作しないため Docker のみ

おまけで Docker や asdf では環境構築できないけど、 Windows 系の Hello, World も

- [PowerShell][ps]
- [VBA]
- [VBS]
- [Windows batch][batch]

## 環境構築方法

### Docker

素早い環境構築といえばこのお方ですね

各言語は [Docker Hub][dh] にイメージを上げているので、それらを使えば一瞬で環境構築できます

```Dockerfile
FROM elixir:1.11.4

WORKDIR /work
```

`docker-compose.yaml` でローカルディレクトリーのマウントを指定すれば、毎回自分のエディターで書いたものをコンテナ内で実行できます

```yaml
version: "3"

services:
  elixir:
    build: .
    container_name: elixir
    tty: true
    volumes:
      - "./scripts:/work"
```

`docker-compose up -d` で起動させたコンテナに `docker exec -it elixir /bin/bash` で入れば、もう実行可能です

```bash
docker-compose up -d
docker exec -it elixir /bin/bash
```

コンテナの中で各言語の仕様に従って実行すれば、すぐに Hello, World! が実行できます

```bash
$ elixir hello.exs
Hello, world!
```

ひととおり動かし終わったらコンテナを止めてください

コンテナから出る

```bash
exit
```

コンテナを停止・削除する

```bash
docker-compose down
```

### asdf

もう一つの手法として、 [asdf] でのインストール方法も載せておきました

こちらはラインタイムバージョン管理ツールで、ローカル環境に簡単に多種言語の多数バージョンをインストールできる

使い方は簡単

まず使いたい言語のプラグインを追加する

```bash
asdf plugin add erlang
asdf plugin add elixir
```

そして、インストールを実行する

```bash
asdf install erlang 24.0.2
asdf install elixir 1.12.1
```

このとき、当該ディレクトリーやその親に `.tool-versions` ファイルがあれば、そこで指定されている言語・バージョンが全てインストールされる

```bash
asdf install
```

これでローカル環境でそのまま各言語が使えるようになる

```bash
$ cd scripts
$ elixir hello.exs
Hello, world!
```

ただし、ローカル環境に言語をインストールするため、インストールの前提となっているパッケージなどは事前にインストールしておく必要がある

例えば、 Ubuntu 20.04 で Elixir の 1.12.1 を使う場合は言語のインストール前に以下を実行する必要がある

```bash
apt install -y \
  automake \
  autoconf \
  build-essential \
  default-jdk \
  fop \
  libgl1-mesa-dev \
  libncurses5-dev \
  libsdl2-dev \
  libsdl2-2.0-0 \
  libssl-dev \
  libxml2-utils \
  unzip \
  xsltproc
```

当然、 Ubuntu のバージョンが違ったり、 CentOS だったり、 macOS　だったりすればまた違ってくる

当然、自分のローカル環境に影響を与えるため、あまり色々入れていると不整合を起こす可能性もある

更に、 Windows だと asdf は使えないため、 WSL 上で実行しなければならない

## 注意点

### プロキシー

プロキシーサーバーがいる場合、 Dockerfile 等々をいじらないと動きません

各種パッケージツール等についても同様です

### ストレージ

Dokcer も asdf も無闇矢鱈とコンテナを立てたり、いろんな言語やバージョンをインストールしていると、ストレージをものすごく消費します

いらなくなったら削除しましょう

Docker使っていないものの一括削除

```bash
docker container prune
docker image prune
```

asdf で不要になった言語、バージョンの削除

```bash
asdf uninstall elixir 1.12.1
```

## まとめ

Docker と asdf のそれぞれで各言語・各バージョンの実行環境を構築した

低リスクですぐに使いたい場合はやはり Docker がおすすめ

ただし、 macOS の Docker がローカルのディレクトリーをマウントしていると遅くなる問題などあるので、じっくり使いたい場合は asdf を使うのがおすすめ

[dart]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/dart/
[elixir]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/elixir/
[elm]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/elm/
[golang]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/golang/
[java]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/java/
[kotlin]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/kotlin/
[markdown]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/markdown/
[nodejs]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/nodejs/
[php]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/php/
[python]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/python/
[r]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/r/
[ruby]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/ruby/
[rust]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/rust/
[scala]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/scala/
[shell]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/shell/
[swift]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/swift/
[ps]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/powershell/
[vba]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/vba/
[vbs]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/vbs/
[batch]: https://github.com/RyoWakabayashi/hello-worlds/tree/main/batch/
[dh]: https://hub.docker.com/
[asdf]: https://github.com/asdf-vm/asdf