Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 47 Anzeige

Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります

※本スライド、旧版のため、下記最新版をご覧ください
https://www.slideshare.net/piacere_ex/elixir1json-81100124

Elixirの「パターンマッチ」と「パイプ」、各種ライブラリを使って、JSON APIを叩き、JSONをパースするアプリをサクっと書いてみます

※本スライド、旧版のため、下記最新版をご覧ください
https://www.slideshare.net/piacere_ex/elixir1json-81100124

Elixirの「パターンマッチ」と「パイプ」、各種ライブラリを使って、JSON APIを叩き、JSONをパースするアプリをサクっと書いてみます

Anzeige
Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Ähnlich wie Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります (20)

Anzeige

Weitere von fukuoka.ex (7)

Aktuellste (20)

Anzeige

Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります

  1. 1. Elixir入門 第1回 「パターンマッチ」&「パイプ」で JSONパースアプリをサクっと書く with Docker 2017/03/29 ver0.5作成 2017/04/06 ver0.9作成 2017/04/13 ver1.0作成 2017/06/07 ver1.1作成
  2. 2. 1 1. Elixirを学ぶと得られること 2. DockerでElixirを使えるようにする 3. はじめてのElixirプログラミング 4. パターンマッチ 5. JSONパースに必要なライブラリ導入 6. パイプ 7. JSONパースアプリを仕上げる 8. 応用①:コードを洗練させる 9. 応用②:Qiita API以外のJSONパース 10.これからElixirを学んでいくあなたへ 目次 ※ページ最下部の章番号/ページは、Dave Thomas著「プログラミングElixir」の関連記載です。ご参考ください
  3. 3. 2 1.Elixirを学ぶと得られること
  4. 4. 3 1.Elixirを学ぶと得られること を学ぶと、以下のような苦難から解放されます a. C10K問題などのソフトウェア性能問題からの解放 b. JSONパーサを手続き的にチマチマ書くことからの解放 c. オブジェクト設計という「余計な仕事」からの解放 d. 他の関数型言語での脱落からの解放 e. 複雑なマルチスレッドプログラミング/デバッグからの解放 f. 1958年に生まれた素晴らしいプログラミングパラダイムを 使いこなせなかった呪いからの解放 結果、プログラミングやプログラマ/エンジニアとしての普段の仕事 が、とても楽しくなります
  5. 5. 4 2.DockerでElixirを使えるようにする
  6. 6. 5 2.DockerでElixirを使えるようにする Elixirを使い始めるのに、3種類の方法があります ① yumやapt/Homebrew/Chocolateyを使う ② 各OS用のElixirをダウンロード、インストールする ③ DockerでElixirイメージをインスト―ル(pull)する このうち、最もてっとり早いのは、③のDockerを使うことです (OS毎の差異影響も受けないのでオススメ) Dockerをインストールしてみましょう https://www.docker.com/get-docker . Dockerが入ったら、以下コマンドでElixirイメージをDLしましょう > docker pull trenpixster/elixir
  7. 7. 6 2.DockerでElixir:ローカルPCのフォルダ共有 ローカルPCのフォルダをDockerでマウントして開発可能とするた め、Docker設定「Shared Drives」でドライブ共有をONします Windowsであれば、その前にWindowsフォルダ共有のポート (TCP/445)にアクセスできるようにしておきます ※ウイルスチェッカーとWindowsファイアウォールの両方にブロック設定がある場合がある
  8. 8. 7 2.DockerでElixir:Elixirの起動 以下コマンドで、Docker上のElixirイメージを起動します ※紫字の部分は、【ローカルPCの共有したいパス】:【Docker上でマウントされるパス】 ElixirのREPL (対話シェル) である「iex」を起動します > docker run --rm -v /c/piacere/code:/code -i -t trenpixster/elixir /bin/bash root@0e27c970ec14:/code# Docker上のElixirイメージ 内にあるbashが起動した # iex Erlang/OTP 19 [erts-8.2] [source-fbd2db2] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false] Interactive Elixir (1.4.1) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> ※参照:第1章 P4
  9. 9. 8 2.DockerでElixir:REPLでのElixir REPL内でElixirの簡単なプログラミングができます iexから抜けてbashに戻るには、Ctrl+cを2回入力します iex(1)> 1+2 3 iex(2)> list = [ 123, "abc", 456, true ] [123, "abc", 456, true] iex(3)> Enum.sort( list ) [123, 456, true, "abc"] iex(4)> map = %{ "key2" => "abc", "key1" => 123 } %{"key1" => 123, "key2" => "abc"} iex(5)> Enum.sort( map ) [{"key1", 123}, {"key2", "abc"}] iex(6)> BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution # リストは[]で囲む マップは%{}で囲む 2種類書き方がある ①%{k1: "v1"…} ②%{"k1" => "v1"…}
  10. 10. 9 3.はじめてのElixirプログラミング
  11. 11. 10 3.はじめてのElixirプログラミング:新規PJ作成 以下コマンドでElixirのプロジェクトを作成します ※紫字の部分は、作成するプロジェクト名 (全部、小文字で打つこと) 以下のようなフォルダ/ファイルが作られます プログラミングするソースコードは、libフォルダ配下に作ります # mix new crawl # pwd;find . | sort | sed '1d;s/^.//;s//([^/]*)$/|--1/;s//[^/|]*/| /g' /code/sample |--_build |--config |--deps |--lib |--mix.exs |--README.md |--test mixはビルドツール ※Railsのbundler+rake的なもの ※参照:第13章 P131
  12. 12. 11 3.はじめてのElixirプログラミング:ビルド、実行 lib/Misc.exを作り、お好きなエディタで以下を入力します ファイル保存したら、以下コマンドでビルドします iexが起動されるので、以下のように作成した関数を実行します defmodule Misc do def sort( values ) do Enum.sort(values ) end end # cd crawl # iex –S mix ーS:フォルダ配下のScript実行 mix:Script名 ※参照:第6章 P45~46、第7章 P63 Elixirは関数をモジュール内に定義します defmodule~end:モジュール定義 def~end:関数定義 iex> Misc.sort( [ 5, 1, 3 ] ) [1, 3, 5] リスト等のコレクションをソートする
  13. 13. 12 3.はじめてのElixirプログラミング:1行関数 関数の呼出時、”()”は省略できます 関数は、以下のように1行でも書け、endも省略できます リストだけで無く、マップも同じ関数定義でソートできます (キー名でソートがかかります) defmodule Misc do def sort( values ), do: Enum.sort( values ) end ※参照:第6章 P47、第8章 P78 iex> recompile() iex> Misc.sort %{ "key2" => "abc", "key1" => 123 } [{"key1", 123}, {"key2", "abc"}] iex> Misc.sort %{ No: "no need", Yes: "need", NA: "N/A" } [NA: "N/A", No: "no need", Yes: "need"] iex> Misc.sort [ 5, 1, 3 ] [1, 3, 5] iexを抜けずにコード変更を反映できる
  14. 14. 13 4.パターンマッチ
  15. 15. 14 4.パターンマッチ:引数でのマッチ いよいよ、他の言語に無い、Elixirのパワフルな面を見ていきます 下記赤囲みの関数を追加してください 以下のように入力して、作成した関数を試します マップの”k2”キーの値抽出を、ナント引数だけで実装できます 他の言語では、そもそも引数では定義不可で、ロジックとして書く のも骨が折れますが、Elixirなら非常にカンタンです defmodule Misc do def match_sample( %{ k2: value } ), do: value … iex> recompile() iex> Misc.match_sample %{ k1: "v1", k2: "v2", k3: "v3" } "v2" ※参照:第6章 P47~49、第8章 P80
  16. 16. 15 4.パターンマッチ:複数関数の呼び分け キーだけで無く、値でマッチしての関数の呼び分けも可能です 以下のように、上と下の関数が、値に応じて、呼び分けされます 他の言語なら、関数呼び出し後にif文で分岐するような処理が、 引数でのパターンマッチで分岐できます (Elixirでも、if文は一応使えるのですが、パターンマッチで片付くので、使う場面があまり無いです) defmodule Misc do def match( %{ Yes: "we can" } ), do: "Barack Obama" def match( %{ Yes: need } ), do: need … iex> recompile() iex> Misc.match %{ No: "-", Yes: "we can", NA: "N/A" } "Barack Obama" iex> Misc.match %{ No: "-", Yes: "we do", NA: "N/A" } "we do" ※参照:第6章 P47~48、第8章 P80
  17. 17. 16 4.パターンマッチ:マッチしない場合 該当キーがマップ内に存在しない場合、マッチエラーになります 引数に”_”を指定すると、その他としてマッチできるようになります defmodule Misc do def match( %{ Yes: "we can" } ), do: "Barack Obama" def match( %{ Yes: need } ), do: need def match( _ ), do: "Yes...NOT EXIST" … iex> Misc.match( %{ No: "-", NA: "N/A" } ) ** (FunctionClauseError) no function clause matching in Crawl.match/1 (crawl) lib/Qiita.ex:5: Crawl.match(%{NA: "N/A", No: "-"}) ※参照:第6章 P47~48 iex> recompile() iex> Misc.match %{ No: "-", NA: "N/A" } "Yes...NOT EXIST"
  18. 18. 17 4.パターンマッチ:関数内でのマッチ もし、関数内でマッチさせるなら、以下のような書き方になります (ただ、関数の引数でマッチする書き方の方が推奨です) 実行結果は、引数パターンマッチ版と同じです defmodule Misc do def match_inner( input_map ) do %{ Yes: need } = input_map need end … iex> recompile() iex> Misc.match_inner %{ No: "-", Yes: "we can", NA: "N/A" } "we can" ※参照:第4章 P27
  19. 19. 18 4.パターンマッチ:リストのパターンマッチ リストは、先頭を「head」、以降を「tail」でパターンマッチできます ※参照:第7章 P64~66、68~69 iex> [ head1 | tail1 ] = [ 5, 8, 3, 1 ] [5, 8, 3, 1] iex> head1 5 iex> tail1 [8, 3, 1] iex> [ head2 | tail2 ] = tail1 [8, 3, 1] iex> head2 8 iex> tail2 [3, 1] …
  20. 20. 19 4.パターンマッチ:リストのパターンマッチ head/tailにより、リストの巡回が可能です リストの要素を先頭から順に拾って繋げるだけなので、引数と全く 変わらないリストが返ります ※参照:第7章 P64~66、68~69 defmodule Misc do def nop( [ head | tail ], rows ), do: nop( tail, rows ++ [ head ] ) def nop( [], rows ), do: rows … iex> recompile() iex> Misc.nop( [ 5, 8, 3, 1 ], [] ) [5, 8, 3, 1]
  21. 21. 20 5.JSONパースに必要なライブラリ導入
  22. 22. 21 5.JSONパースに必要なライブラリ導入 JSONパーサアプリを書く前段として、ElixirのHTTPclientであ るHTTPoisonと、JSONparserであるPoisonを導入します まず、mix.exsに下記赤囲み部分を追加してください 次に、以下コマンドで各モジュールを取得します(要ネット接続) defmodule Crawl.Mixfile do … defp deps do [ { :httpoison, "~> 0.7.2" }, { :poison, "~> 1.5" } ] end end # mix deps.get ※参照:第13章 P137~143
  23. 23. 22 追加したモジュールを使い、Qiita API呼出と、返ってくるJSON (以下参照)のパースを行います 5.JSONパースに必要なライブラリ導入
  24. 24. 23 lib/Crawl.exを作り、HTTPoisonでQiita APIの呼び出しを 行うコードを書きます 実行すると、Qiitaから取得したJSONが出力されます 前ページで見たBody部だけで無く、StatusCode等も見れます defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) end end # iex –S mix iex> Crawl.get %HTTPoison.Response{body: "[{"rendered_body":"nu003ch2u003en … ,"title":"AWS EC2にElixir/Phoenixをインストール","updated_at":"2017-02-10T13:08:41+09:00", …(他記事が複数並ぶ)… "twitter_screen_name":null,"website_url":null}}]", …(Body部以外のHeader等が複数並ぶ)… {"Content-Length", "4293"}, {"Connection", "keep-alive"}], status_code: 200} 5.JSONパースに必要なライブラリ導入 ※参照:第13章 P137~143
  25. 25. 24 5.JSONパースに必要なライブラリ導入 StatusCodeが取得成功を示す「200」のときだけ、Body部を 抜き出し、パターンマッチしやすい変換を行います 変換後のBody部だけが出力されます defmodule Crawl do def get() do response = HTTPoison.get!( "https://qiita.com/api/v2/items?query= Elixir" ) body = body( response ) Poison.decode!( body ) end def body( %{ status_code: 200, body: json_body } ), do: json_body end iex> recompile() iex> Crawl.get [%{"body" => "# ElasticBeanstalk Custom Platformとは?nn今までのElasticBeanstalkでは事前定義済み … "title" => "AWS EC2にElixir/Phoenixをインストール", …(他記事が複数並ぶ)… "twitter_screen_name" => nil, "website_url" => nil}}] ※参照:第13章 P137~143
  26. 26. 25 6.パイプ
  27. 27. 26 作ったget()を見ると、Qiita取得→Body抽出→JSONデコード という流れを、変数で受け渡しており、まどろっこしいです 一方、変数を無くすと、流れと逆になるため、読みにくいです defmodule Crawl do def get() do response = HTTPoison.get!( "https://qiita.com/api/v2/items?query= Elixir" ) body = body( response ) Poison.decode!( body ) end … ※参照:第6章 P54~55 6.パイプ defmodule Crawl do def get() do Poison.decode!( body( HTTPoison.get!( "https://qiita.com/api/v2/items? query=Elixir" ) ) ) …
  28. 28. 27 Elixirでは、これを直感的かつスマートに書けて、ステキです "|>"はパイプ演算子と呼ばれ、前の処理の出力を、次の処理 の第1引数として暗黙で渡します 引数が複数ある場合は、第2引数以降を()で指定も可能です ※下記はサンプルなので動きません defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! end … 6.パイプ ※参照:第6章 P54~55 HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body( %{ status_code: _ }, "ERROR: not 200" ) |> Poison.decode!
  29. 29. 28 7.JSONパースアプリを仕上げる
  30. 30. 29 7.JSONパースアプリを仕上げる これまで作成したコードをベースに、「Qiita APIを呼び、記事タイ トルをリストアップするアプリ」に仕上げていきましょう Poison.decodeでパターンマッチしやすく変換されたBodyは、 以下のような、「1記事1マップ」をリストでまとめたフォーマットに なっています 記事タイトルのリストアップには、このリストを巡回し、各マップの titleを抽出すればOKです [ %{"body" => "【1件目の記事内容】", "created_at" => "【作成日】", "title" => "【1件目の記事タイトル】"}, %{"body" => "【2件目の記事内容】", "created_at" => "【作成日】", "title" => "【2件目の記事タイトル】"}, … %{"body" => "【n件目の記事内容】", "created_at" => "【作成日】", "title" => "【n件目の記事タイトル】"} ]
  31. 31. 30 記事タイトルを抽出するコードを追加します 上のtitle_list()は、変換されたBodyのリストを第1引数で受け、 抽出したタイトルを溜め込むリストを第2引数としています 7.JSONパースアプリを仕上げる defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list( [] ) end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles title_list( tail, added_titles ) end def title_list( [], titles ), do: titles end ※参照:第7章 P64~66、68~69
  32. 32. 31 Bodyリストの先頭マップを「head」、以降のマップ群を「tail」で 扱えるようにし、head内に存在する”title”キーの値、つまり記事 タイトルをパターンマッチで抽出し、「json_title」に持たせます 7.JSONパースアプリを仕上げる:タイトルの抽出 defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list( [] ) end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles title_list( tail, added_titles ) end def title_list( [], titles ), do: titles end ※参照:第4章 P27
  33. 33. 32 抽出したタイトルを”[”と”]”で囲むことでリスト化し、”++”でタイ トルを溜め込むリストである「titles」の先頭に連結します なお、初回時は、titlesには空リストである[]が渡されています 7.JSONパースアプリを仕上げる:タイトルの連結 defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list( [] ) end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles title_list( tail, added_titles ) end def title_list( [], titles ), do: titles end ※参照:第7章 P75
  34. 34. 33 以降のマップ群「tail」に対し、引き続き、抽出を行うため、 title_list()を再度呼びます tailが空リストになったら、下のtitle_list()が呼ばれ、完了です 7.JSONパースアプリを仕上げる:再帰リスト処理 defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list( [] ) end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles title_list( tail, added_titles ) end def title_list( [], titles ), do: titles end ※参照:第7章 P68~69
  35. 35. 34 titleの抽出を、まず簡単なデータでテストします うまく抽出できました 次に、Qiita記事でtitleを抽出します こうして、たった15行のコードで、「Qiita APIを呼び、記事タイト ルをリストアップするアプリ」が書けました 7.JSONパースアプリを仕上げる iex> recompile() iex> Crawl.title_list [ %{ "body" => "b1", "title" => "t1" }, %{ "body" => "b2", "title" => "t2" } ] ["t2", "t1"] iex> Crawl.get ["Advent Calendar 2016 投稿数の多いユーザランキング(上位50位)", "スタートアップ企業の技術選定でPhoenix(Elixir)&React(JS)+時々Echo(go)を採用した", "弊社で検討したフルスタック寄りWebアプリケーションフレームワークの比較", "PhoenixでAPIによるログイン機能を実装する", "新人(候補)を教育することになったので、弊社の教育方針と教材まとめの記事(リンク集)を作っておく", …(他記事が複数並ぶ)… "Elixir/Phoenix環境をElasticBeanstalk Custom Platformで構築してみた"]
  36. 36. 35 書かれたコードを見直すと、タイトル抽出は比較的難しいものの、 メインの処理は、JSON取得→Body抽出→JSONデコード→ 複数title抽出と、とても直感的で分かりやすいコードです 7.JSONパースアプリを仕上げる defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list( [] ) end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles title_list( tail, added_titles ) end def title_list( [], titles ), do: titles end
  37. 37. 36 8.応用① コードを洗練させる
  38. 38. 37 より直感的なコードに改善できます 第1引数でBodyのみ受けるtitle_list()を設けることで、最初は 空が確定している空リストの指定が省略できます 8.応用① コードを洗練させる:自明な引数の省略 defmodule Crawl do def get() do HTTPoison.get!( "https://qiita.com/api/v2/items?query=Elixir" ) |> body |> Poison.decode! |> title_list end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( body ), do: _title_list( body, [] ) defp _title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles _title_list( tail, added_titles ) end defp _title_list( [], titles ), do: titles end ※参照:第7章 P69
  39. 39. 38 URL指定も関数化し、検索キーワードもパラメータ化します パイプで簡単に処理を継ぎ足せるのが、Elixirらしいところです 8.応用① コードを洗練させる:URL指定の分離 defmodule Crawl do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> title_list end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( body ), do: _title_list( body, [] ) defp _title_list( [ head | tail ], titles ) do %{ "title" => json_title } = head added_titles = [ json_title ] ++ titles _title_list( tail, added_titles ) end defp _title_list( [], titles ), do: titles def url( query ), do: "https://qiita.com/api/v2/items?query=#{query}" end #{~}で、引数や変数の値を展開できる ””でパラメータ未指定時のデフォルト引数が指定可能
  40. 40. 39 「head」と「tail」を関数内でパターンマッチしている部分を、引数 で”title”を直接パターンマッチするようにし、title連結部分も”|” でのリスト連結に変えれば、よりコードが短縮できます ※やや難しいので、今はニュアンスを理解する程度でもOKです 8.応用① コードを洗練させる:リスト巡回の短縮 defmodule Crawl do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> title_list end def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( body ), do: _title_list( body, [] ) defp _title_list( [ %{ "title" => json_title } | tail ], titles ) do _title_list( tail, [ json_title | titles ] ) end defp title_list( [], titles ), do: Enum.reverse( titles ) def url( query ), do: "https://qiita.com/api/v2/items?query=#{query}" end ※参照:第6章 P54
  41. 41. 40 8.応用① コードを洗練させる:モジュール分離 共通ロジックを別モジュールに括りだします Parse.exを以下内容で作成し、Crawl.ex側も修正します defmodule Parse do def body( %{ status_code: 200, body: json_body } ), do: json_body def title_list( body ), do: _title_list( body, [] ) defp _title_list( [], titles ), do: titles defp _title_list( [ %{ "title" => json_title } | tail ], titles ) do _title_list( tail, [ json_title | titles ] ) end end Parse.ex Crawl.ex defmodule Crawl do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> Parse.body |> Poison.decode! |> Parse.title_list end def url( query ), do: "https://qiita.com/api/v2/items?query=#{query}" end
  42. 42. 41 9.応用② Qiita API以外のJSONパース
  43. 43. 42 9.応用② Qiita API以外のJSONパース Qiita API以外のAPIも、ほぼ同じコードでJSONパースできます 「はてなAPI」のJSONは、若干壊れている (笑) ので、デコード 前に文字列操作で補正をかけるパイプを追加します defmodule Hatena do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> Parse.body |> String.slice( 1..-3 ) # そのままだとinvalidなJSONなので加工 |> Poison.decode! |> Parse.title_list end def url( query ), do: "http://b.hatena.ne.jp/entrylist/json?sort=count&url=#{query}" end Hatena.ex # iex -S mix iex> Hatena.get ["【翻訳】超高速なJSON APIをElixirフレームワークのPhoenixでビ...", "2015/08/22/ElixirとPhoenixとMithrilのFFスタックでChatアプリを作っ...", …(他記事が複数並ぶ)… " Elixir ご紹介 // Speaker Deck"]
  44. 44. 43 9.応用② Qiita API以外のJSONパース 「Wikipedia API」のJSONは、Qiita APIより2段、深い階層 構造なので、titleを抽出できる階層まで下るパイプを追加します defmodule Wikipedia do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> Parse.body |> Poison.decode! |> dig |> Parse.title_list end def url( query ), do: "https://ja.wikipedia.org/w/api.php?format=json&action=query &list=search&srsearch=#{query}" def dig( %{ "query" => %{ "search" => search } } ), do: search end Wikipedia.ex # iex -S mix iex> Wikipedia.get ["熊沢千絵", "プログラミング言語一覧", …(他記事が複数並ぶ)… "エリクサー"]
  45. 45. 44 9.応用② Qiita API以外のJSONパース 「Github API」は、検索パラメータの指定が異なるので、検索パ ラメータに渡すデフォルト値を変えます defmodule Github do def get( query "Elixir-lang/Elixir" ) do # 例.rails/rails url( query ) |> HTTPoison.get! |> Parse.body |> Poison.decode! |> Parse.title_list end def url( query ), do: "https://api.github.com/repos/#{query}/issues" end Github.ex # iex -S mix iex> Wikipedia.get ["Use @optional_callbacks in GenServer", "Improve no function clause error messages", …(他記事が複数並ぶ)… "Make Mix more friendly for newcomers"]
  46. 46. 45 10.これからElixirを学んでいくあなたへ
  47. 47. 46 10.これからElixirを学んでいくあなたへ 今回は、Elixirの入門ということで、パターンマッチやパイプといった Elixirの基本的な機能についてご説明しました 関数型言語が、「そこまで難しく無いかも?」と思っていただけたら この入門としては大成功です Java等のオブジェクト言語に慣れた方ほど、とっつき難いところが 関数型言語にはありますが、Elixirは入門向きだと思います 逆に、プログラミングはこれから、という方にとっては、余計な知識 を入れずにElixirを直感で理解できる、良い機会です 仕事でも趣味でも、プログラミングライフをエンジョイしてください!

×