naoya@githubさんが最近「カッとなって」Elixir関連の記事を投稿されていますが、さらにカッとなってWEB+DB PRESSに記事を書かれています。
でも、あのソースを見てもそのままでは実際に動かせなかった人も多いのでは。次号以降に補足が出るにしても隔月刊ですしね…
ということで復習も兼ねて動かし方を書いてみます。
ソース
ソースはこんな感じでした(写経)。一つ目の「あまりElixirらしくない」ものを対象にしました。
defmodule WeatherClient do
def fetch_json(url) do
HTTPoison.start
res = HTTPoison.get!(url)
Poison.decode!(res.body)
end
def get do
%{"weather" => weather} = fetch_json(
"http://api.openweathermap.org/data/2.5/weather?q=Tokyo.jp"
)
weather
end
end
Enum.each WeatherClient.get, fn(w) ->
IO.puts w["main"]
end
依存性のあるライブラリ
ここでは2つの依存性のあるライブラリが使われています1。
HTTPoison
HTTPクライアントライブラリ。ErlangのHTTPクライアントライブラリhackneyをベースに作られている。以前に使いました。プロキシ設定が使えるのがうれしいケースもあり。
Poison
JSONライブラリ。Githubによれば単純さや完全さや正確さを全く犠牲にせず爆速、とのこと。
ですので、これらをどうにかして持ってきて使う必要があります。
mix new でプロジェクトを作り mix.exsを設定する
ではmixでプロジェクトを作ります。
$ mix new weatherclient --module WeatherClient
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/weatherclient.ex
* creating test
* creating test/test_helper.exs
* creating test/weatherclient_test.exs
Your mix project was created successfully.
You can use mix to compile it, test it, and more:
cd weatherclient
mix test
Run `mix help` for more commands.
--module WeatherClient
を付けたのはモジュール名をCamelCase(WeatherClient)にしたかったから。付けないとWeatherclientになります(そうなると写経したプログラムの方も合わせる必要があるのでめんどくさい)。
次に依存関係のあるライブラリを使うためにmix.exs
を変更します。
$ cd weatherclient
$ ls
config lib mix.exs README.md test
$ vi mix.exs
(おっと、Vimmerなのがバレてしまった)お好みのエディタでmix.exsを以下のように変更します。
defmodule WeatherClient.Mixfile do
use Mix.Project
def project do
[app: :weatherclient,
version: "0.0.1",
elixir: "~> 1.0",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps]
end
# Configuration for the OTP application
#
# Type `mix help compile.app` for more information
def application do
[applications: [:logger]]
end
# Dependencies can be Hex packages:
#
# {:mydep, "~> 0.3.0"}
#
# Or git/path repositories:
#
# {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
#
# Type `mix help deps` for more examples and options
defp deps do
[
{:httpoison, "~> 0.6"},
{:poison, "~> 1.4.0"}
]
end
end
defp deps do
のところがもともと[]
になっているのでここに必要なライブラリ名とバージョン(~>
は...以上の意)を設定します。
mix deps.getで必要なものを落としてくる
mix deps.get
で必要なライブラリを落としてきましょう。
$ mix deps.get
Running dependency resolution
Dependency resolution completed successfully
hackney: v1.3.1
httpoison: v0.7.2
idna: v1.0.2
poison: v1.4.0
ssl_verify_hostname: v1.0.5
* Getting httpoison (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/httpoison-0.7.2.tar)
...(中略)...
* Getting idna (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/idna-1.0.2.tar)
Using locally cached package
Unpacked package tarball (/home/azureuser/.hex/packages/idna-1.0.2.tar)
次はlib/webclient.ex
が最初は
defmodule WeatherClient do
end
という内容だけなのでこのファイルに「写経」します。
ビルドして実行する
mix run
を実行します。
$ mix run
==> idna (compile)
Compiled src/idna.erl
...(中略)...
Compiled src/hackney_connect/hackney_cacerts.erl
Compiled src/hackney_lib/hackney_mimetypes.erl
==> httpoison
Compiled lib/httpoison/base.ex
Compiled lib/httpoison.ex
Generated httpoison app
Clouds
==> weatherclient
Compiled lib/weatherclient.ex
Generated weatherclient app
おしまいの方にちょろっと
Clouds
(曇り)
と出てるのが結果です。
2回めからは
$ mix run lib/weatherclient.ex
と実行してください。
lib/weatherclient.ex:1: warning: redefining module WeatherClient
Clouds
と結果の前に警告が出ますが気にしなくていいようです。
iex -S mixを使う
プログラムが実際何をやっているか見るにはiex
を使いましょう。
$ iex -S mix
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
ここでモジュールWeatherClientの関数を直に叩くと
iex(1)> WeatherClient.get
[%{"description" => "overcast clouds", "icon" => "04n", "id" => 804,
"main" => "Clouds"}]
という中身が返ってきていることがわかります2。元のプログラムの一番下3行はこの結果の中からキー"main"の値の部分だけ取り出していたのです。続けて確認しましょう。
iex(2)> Enum.each WeatherClient.get, fn(w) ->
...(2)> IO.puts w["main"]
...(2)> end
Clouds
:ok
iex(3)>