Open7

Elixir ことはじめ

m_takeharam_takehara

環境構築

目標

  • 作業 OS: Windows
  • IDE: VS Code
  • Elixir 動作環境: Docker コンテナ (elixir:latest)
    • (Windows 環境に色々インストールしたくない)
  • ファイル保存先: WSL
    • (File sharing の警告を受けたくない)

インストールしておくもの

  • WSL 2 (Ubuntu)
  • Docker
  • VS Code

手順

Elixir が動作するターミナルを触れるようになるまで

  1. WSL 環境内に, 以下のようなファイル構造を作る
    /usr/local/
        └ elixir_example
            ├ .devcontainer
            │  ├ devcontainer.json
            │  └ Dockerfile
            └ (ここにプロダクトコードを置いていく)
    
  2. devcontainer の中身を入力
    {
        "name": "elixir_example",
        "dockerFile": "Dockerfile",
        "settings": {
            "terminal.integrated.shell.linux": "bash"
        }
    }
    
  3. Dockerfile の中身を入力
    FROM elixir:latest
    
  4. $ cd /usr/local/elixir_example
  5. $ code ./usr/local/elixir_example が VS Code で開かれる
  6. Ctrl + Shift + P → コマンド入力欄が開く
  7. Remote-Containers: Reopen in Container を実行
  8. Ctrl + @ で Bash (in Docker コンテナ) が開く

Elixir プロジェクトの初期化

  1. $ mix new .
    • ↑新規プロジェクトのテンプレートを生成
    • Mix: Elixir のビルドツール, コンテナ内にインストール済
  2. $ mix test → テストが実行成功できれば OK
m_takeharam_takehara

実行ファイル · Elixir School

とりあえず Hello World したい場合は以下のようにファイルを書き換える

diff --git a/lib/elixir_example.ex b/lib/elixir_example.ex
index 21ea16a..547bf7a 100644
--- a/lib/elixir_example.ex
+++ b/lib/elixir_example.ex
@@ -12,7 +12,7 @@ defmodule ElixirExample do
       :world
 
   """
-  def hello do
-    :world
+  def main(_args) do
+    IO.puts("Hello, Elixir!")
   end
 end
diff --git a/mix.exs b/mix.exs
index 41eff64..4a1abbd 100644
--- a/mix.exs
+++ b/mix.exs
@@ -7,7 +7,10 @@ defmodule ElixirExample.MixProject do
       version: "0.1.0",
       elixir: "~> 1.11",
       start_permanent: Mix.env() == :prod,
-      deps: deps()
+      deps: deps(),
+      escript: [
+        main_module: ElixirExample
+      ]
     ]
   end
 

そしてビルド → 実行

$ mix escript.build
$ ./elixir_example
m_takeharam_takehara

FizzBuzz

defmodule ElixirExample do
  @error {:error, "Invalid arguments."}
  def main(args) do
    {status, result} = parse_args(args)

    case status do
      :ok -> result |> get_fizz_buzz() |> Enum.each(&IO.puts(&1))
      :error -> IO.puts(result)
    end
  end

  defp parse_args([]), do: @error

  defp parse_args(args) do
    [head | tail] = args
    regex = ~R/[1-9][0-9]*/

    case {head =~ regex, tail} do
      {true, []} -> {:ok, String.to_integer(head)}
      {_, _} -> @error
    end
  end

  defp get_fizz_buzz(count), do: 1..count |> Enum.map(&to_fizz_buzz/1)

  defp to_fizz_buzz(num), do: to_fizz_buzz(rem(num, 3), rem(num, 5), num)
  defp to_fizz_buzz(0, 0, _), do: "FizzBuzz"
  defp to_fizz_buzz(0, _, _), do: "Fizz"
  defp to_fizz_buzz(_, 0, _), do: "Buzz"
  defp to_fizz_buzz(_, _, n), do: n
end