27 Jun 2014

Guessing Game

ExUnitとMixの使い方についてです。

昨日はElixir Guessing Gameという投稿を見つけたので、この方法にならって進めました。

詳しくはこの投稿を見てもらうとして、MixはBundlerのように、bundle gemコマンドにあたるのがmix newというコマンドです。

また、テスト駆動の方法を紹介しているので親切な印象を受けました。

まず文中の:random.uniformという記述はErlangのrandomを直接呼び出しているようです。

また、Erlangのrandom.uniformは引数なしでFloatの乱数、random.uniform(10)とすると、整数の範囲内で乱数を返します。

Rubyの感覚でrandom.uniform(10..20)とすると、エラーが発生してしまうようです。そこで、elixir-randomを利用するとRandom.sample(10..20)というように範囲内の乱数が返ってきます。

NOTE: Erlangだけで範囲の乱数を取得する場合はrandom.uniform(10) + 10です。

Elixirではrequireとかimportのような記述をしなくてもモジュール単位でファイルを読み込んでくれるようです。iexでファイルを読む必要があるならば、mix.exsのあるディレクトリでiex -S mixです。

def check_user_input(number) when number <= 10 do
    {:ok, number}
end

文中にあるこのコードですが、numberが1以上且つ、10以下である条件に書き換えようとしたところ、エラーが発生してしまいました。

iex> def check_user_input(number) when number <= 10 and number > 0 do
...>   {:ok, number}
...> end
** (ArgumentError) cannot invoke def/2 outside module
    (elixir) lib/kernel.ex:3748: Kernel.assert_module_scope/3
    (elixir) lib/kernel.ex:2980: Kernel.define/4
    (elixir) expanding macro: Kernel.def/2
    (elixir) iex: :elixir_compiler.__FILE__/2

これを修正する方法はbeamのチャットで教えていただいたのですが&&のかわりにandを定義されたモジュールの中で書き換えます。

defmodule GuessingGame do
  def check_user_input(number) when (number <= 10 and number > 0) do
    {:ok, number}
  end
end

これで先ほどのテストが無事通りました。

User Interface以降がまだうまくいかなかったため、次回に続きます。