#目的
ElixirからSheriffを使ってみた・・・かったorz
本来の目的は、Validationをテストすることであった。
詳しく理由・・・
Phoenix - Guide Overviewもしくは、Qiita - Phoenix Framework(v0.13) 概要の記事の中に、
Cowboyの項目でSheriffは型ベースの動的なValidation...と書いてあった。
そのため、いずれ使用するであろうValidationを一足先にテストすることであった。
その様がこれだよ・・・orz
#構築している環境
OS: Windows8.1
Erlang: Eshell V6.4
Elixir: v1.0.4
Sheriff: バージョン不明 (github)
#目次
1. "mix new"でプロジェクト作成
2. Sheriffを早速!使ってみよう!!
3. だめだったよ・・・調査だ!調査!!
4. やっぱりだめだったよ
5. まとめ
#参考文献
Sheriff README
http://erlang.org/doc/reference_manual/typespec.html
http://elixir-lang.org/docs/v1.0/elixir/Kernel.Typespec.html
http://elixir-lang.org/getting-started/typespecs-and-behaviours.html
#情報提供求む
どなたか情報や知識がおありの方、
記事を読んで、もしかしてこれが原因とか、こうしたらどうだろうかといった考察がおありでしたらコメントして頂けると嬉しいです。
##1. "mix new"でプロジェクト作成
>cd 作業ディレクトリ
>mix new プロジェクト名
私は"elixir_use_sheriff"と命名。以降この名称で記述する。
>cd elixir_use_sheriff
>mix test
異常なし!!
mix.exsは以下の通り編集した。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ElixirUseSheriff.Mixfile do | |
use Mix.Project | |
def project do | |
[app: :elixir_use_sheriff, | |
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 | |
[ | |
{:sheriff, github: "extend/sheriff"} | |
] | |
end | |
end |
>mix deps.get
これでプロジェクト作成完了!!
##2. Sheriffを早速!使ってみよう!!
参考にするソースコードは公式のREADME!!
Sheriff README
っと言っても・・・
これと
-type colors() :: blue | red | green | yellow.
これ
sheriff:check(Color, colors)
上記の二行をErlangからElixirコードに変換する・・・だけ。(想定では)
この時、管理人はまだ知らなかったのです。
朝から始めて夜になっても終わらないことを・・・
プロジェクト作成の時生成されているソースコードを編集する。
/lib/elixir_use_sheriff.ex
まずは、このコードを変換する。
-type colors() :: blue | red | green | yellow.
Erlangのドキュメントを見る。
http://erlang.org/doc/reference_manual/typespec.html
続いて、Elixirのドキュメントを見る。
http://elixir-lang.org/docs/v1.0/elixir/Kernel.Typespec.html
ん?Getting Startの方もあった。
http://elixir-lang.org/getting-started/typespecs-and-behaviours.html
ふむふむ、何となく分かった!!(気がする・・・変わらず英語に弱い)
Erlangでは、小文字で始まるものはatomのはず、
また、-typeはそのまま@typeに変換する。
ドキュメント見る限りはこれで問題ないはず・・・
定義場所はモジュールの中に定義する。
とりあえず、こんな感じで変換。
@type colors() :: :blue | :red | :green | :yellow
よっし、じゃあコンパイルしよう!
>mix compile
ん~、エラー出てないし記法的な問題はないっぽいね。
んじゃ、次!!
このコードを変換だ!
sheriff:check(Color, colors)
事前学習はしてきたぜ!!
まずは、適当に関数を作成する。
Erlangのライブラリを使う時は、:(コロン)を付けてモジュールを記述する。
例) :erlang.size("test")
----
def test(color) do
:sheriff.check(color, colors)
end
----
コンパイル、コンパイル~
>mix compile
ん?エラー出た。
----
** (CompileError) lib/elixir_use_sheriff.ex:5: function colors/0 undefined
(stdlib) lists.erl:1336: :lists.foreach/2
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
----
undefined・・・定義されてないだと?
ここら辺から段々と雲行きが怪しくなる・・・
##3. だめだったよ・・・調査だ!調査!!
う~む、出てしまったものはどうしようもない。
とりあえず、Erlangのソースコードから関数の動作を予想しよう。
見る限りだとシンプルな内容である。
引数(アリティ)は2つ、checkで検証している。(check/2)
第一引数は、おそらくatomで色を指定するのだろう・・・
第二引数は、検証する時の該当色・・・つまり-typeで一致させる一覧を定義しているのだろう・・・
っと予想した。
とりあえず、べた書きするか・・・
この部分を第二引数に記述する。
:blue | :red | :green | :yellow
っとこうなる。
:sheriff.check(color, :blue | :red | :green | :yellow)
でも、ちょとまてちょとまてお兄さん!
引数二つですよ?しゃーないから、タプルにする。
こうなった。
:sheriff.check(color, {:blue | :red | :green | :yellow})
>mix compile
またエラー?しょうがないな~
何々、|(パイプライン)が定義されていない?
タプルでこの書き方できたっけ?(Elixir力が低いことが露呈し始める・・・)
----
** (CompileError) lib/elixir_use_sheriff.ex:5: function '|'/2 undefined
(stdlib) lists.erl:1336: :lists.foreach/2
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
----
タプル調べた。,(カンマ)に変えてみる。
:sheriff.check(value, {:blue, :red, :green, :yellow})
おっ!?通った!!
よしこれでテストができる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ElixirUseSheriff do | |
@type colors() :: :blue | :red | :green | :yellow | |
def test(value) do | |
:sheriff.check(value, {:blue, :red, :green, :yellow}) | |
end | |
end |
mixで取ってきたライブラリも含めてiexで使えるようにする起動オプションでコマンドを叩く。
>iex -S mix
iex(1)> ElixirUseSheriff.test(:blue)
false
動いた!?あれでも待って・・・想定してる動作してないよ!!
(Why!! Elixir Program!!!!)
とりあえず動作はした。でも、想定している動作はしていない。
こいつはどうやら、check/2自体を検証してみるしかないな・・・
##4. やっぱりだめだったよ
再びiexより・・・
>iex -S mix
iex(1)> h(:sheriff.check/2)
:sheriff was not compiled with docs
あ・・・ヘルパー関数でドキュメント見ようと思ったけど、
ドキュメントはコンパイルしてないみたいね。
仕方ない・・・直接幾つかパターンをcheck/2で試してみよう・・・
まずはべた書き・・・
実例1) :sheriff.check(:blue, :blue)
結果: false
実例2) :sheriff.check(1, 1)
結果: false
実例3) :sheriff.check("test", "test")
結果: false
!?
まさかの全部だめ・・・あれ、これやばくね?
次、Elixir Kernel.Typespecのドキュメントに型が記述されていた。
あれを使ってみよう!!
実例1) :sheriff.check(1, Integer)
結果: false
Integerはモジュールだよね・・・
実例2) :sheriff.check(1, integer)
結果: ** (RuntimeError) undefined function: integer/0
エラー・・・
実例3) :sheriff.check(1, :integer)
結果: false
atomを指定してどうするのか・・・
この後、次々と色々なパターンを試してみたが駄目だった・・・
sheriffのソースコードを見てみるも・・・
Erlangレベルが低いため、なんとなくしかやっていることは分からず・・・
自分の頭では限界なので、ネットに解決の糸口がないか探しに旅に出た。
これは!?っと思うものを探し、試行錯誤してみるも空しい結果に終わった・・・
しかも行き着くサイトはほとんど、GithubかStackOverflow、海外サイトである。
英語はもういやだ・・・
そして手詰まり・・・お手上げ・・・もう無理ぽ(´・ω・`)
##5. まとめ
何がいけないのか少し考察してみた。
これって言うのはないが、多分ここら辺調べればいいんじゃね?くらいのレベルだが・・・
・check/2の引数に対しての認識が間違っている?
・check/2関数本体の動作予測が間違っている?
・@typeの使い方間違えているんじゃないか?
・変換したコードだとElixir側では足りないものがある?
・実は根本的に、ElixirでのSheriffの使い方が間違っている?
とりあえず、こんなところかな~
Typeや型に対しての認識、Erlang力、Elixir力が足りないと言うのは分かった。
ElixirでValidationするだけなら他にもライブラリあるし!!!!(涙目・・・)
以上・・・誰か救いの手を下さい・・・