Soumettre la recherche
Mettre en ligne
やや関数型を意識した風Elixir/Phoenixご紹介
•
5 j'aime
•
1,953 vues
fukuoka.ex
Suivre
やや関数型を意識した内容のElixir/Phoenixをご紹介するスライドです
Lire moins
Lire la suite
Ingénierie
Signaler
Partager
Signaler
Partager
1 sur 35
Recommandé
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
fukuoka.ex
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
fukuoka.ex
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
fukuoka.ex
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
fukuoka.ex
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
fukuoka.ex
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
fukuoka.ex
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
fukuoka.ex
Reading Anorm 2.0
Reading Anorm 2.0
Kazuhiro Sera
Recommandé
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
fukuoka.ex
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
fukuoka.ex
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
fukuoka.ex
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
fukuoka.ex
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
fukuoka.ex
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
fukuoka.ex
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
fukuoka.ex
Reading Anorm 2.0
Reading Anorm 2.0
Kazuhiro Sera
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XML
ShinichiAoyagi
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
kwatch
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
CodeIgniter入門
CodeIgniter入門
Sho A
Terraform
Terraform
Shigeyuki Takeuchi
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
実"戦"CakePHP Plugin
実"戦"CakePHP Plugin
Kenichirou Oyama
Embulk 20150411
Embulk 20150411
Hiroshi Nakamura
Zabbix API
Zabbix API
Shuhei Hayashibara
PHPの今とこれから2014
PHPの今とこれから2014
Rui Hirokawa
Ansible 入門 #01 (初心者向け)
Ansible 入門 #01 (初心者向け)
Taro Hirose
PHPコアから読み解くPHP5.5
PHPコアから読み解くPHP5.5
Yahoo!デベロッパーネットワーク
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Masahiro Nagano
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
なおき きしだ
How to contribute AWX
How to contribute AWX
Hideki Saito
Perl 非同期プログラミング
Perl 非同期プログラミング
lestrrat
Development app-with-elixir
Development app-with-elixir
k1complete
LINQ in Unity
LINQ in Unity
Yoshifumi Kawai
Em synchrony について
Em synchrony について
Tomoya Kawanishi
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
do_aki
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
Shogo Sensui
Contenu connexe
Tendances
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XML
ShinichiAoyagi
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
kwatch
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
CodeIgniter入門
CodeIgniter入門
Sho A
Terraform
Terraform
Shigeyuki Takeuchi
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
実"戦"CakePHP Plugin
実"戦"CakePHP Plugin
Kenichirou Oyama
Embulk 20150411
Embulk 20150411
Hiroshi Nakamura
Zabbix API
Zabbix API
Shuhei Hayashibara
PHPの今とこれから2014
PHPの今とこれから2014
Rui Hirokawa
Ansible 入門 #01 (初心者向け)
Ansible 入門 #01 (初心者向け)
Taro Hirose
PHPコアから読み解くPHP5.5
PHPコアから読み解くPHP5.5
Yahoo!デベロッパーネットワーク
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Masahiro Nagano
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
なおき きしだ
How to contribute AWX
How to contribute AWX
Hideki Saito
Perl 非同期プログラミング
Perl 非同期プログラミング
lestrrat
Development app-with-elixir
Development app-with-elixir
k1complete
LINQ in Unity
LINQ in Unity
Yoshifumi Kawai
Em synchrony について
Em synchrony について
Tomoya Kawanishi
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
do_aki
Tendances
(20)
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XML
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CodeIgniter入門
CodeIgniter入門
Terraform
Terraform
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
実"戦"CakePHP Plugin
実"戦"CakePHP Plugin
Embulk 20150411
Embulk 20150411
Zabbix API
Zabbix API
PHPの今とこれから2014
PHPの今とこれから2014
Ansible 入門 #01 (初心者向け)
Ansible 入門 #01 (初心者向け)
PHPコアから読み解くPHP5.5
PHPコアから読み解くPHP5.5
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
How to contribute AWX
How to contribute AWX
Perl 非同期プログラミング
Perl 非同期プログラミング
Development app-with-elixir
Development app-with-elixir
LINQ in Unity
LINQ in Unity
Em synchrony について
Em synchrony について
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
Similaire à やや関数型を意識した風Elixir/Phoenixご紹介
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
Shogo Sensui
IdrisでWebアプリを書く
IdrisでWebアプリを書く
Hideyuki Tanaka
Haskell で CLI
Haskell で CLI
Nobutada Matsubara
たのしい関数型
たのしい関数型
Shinichi Kozake
Everyday Life with clojure.spec
Everyday Life with clojure.spec
Kent Ohashi
Lisp batton - Common LISP
Lisp batton - Common LISP
Masaomi CHIBA
ATN No.2 Scala事始め
ATN No.2 Scala事始め
AdvancedTechNight
実践 Reactive Extensions
実践 Reactive Extensions
Shin Ise
MlnagoyaRx
MlnagoyaRx
Shoichi Kakamu
Ajax 応用
Ajax 応用
Katsuyuki Seino
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming Paradigm
Minero Aoki
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
mganeko
J qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているか
Hisashi Aruji
Xtext 紹介
Xtext 紹介
Akira Tanaka
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Preferred Networks
Ext.directことはじめ
Ext.directことはじめ
Shuhei Aoyama
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programming
Tomoharu ASAMI
VS勉強会 .NET Framework 入門
VS勉強会 .NET Framework 入門
kamukiriri
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
TanUkkii
Similaire à やや関数型を意識した風Elixir/Phoenixご紹介
(20)
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
IdrisでWebアプリを書く
IdrisでWebアプリを書く
Haskell で CLI
Haskell で CLI
たのしい関数型
たのしい関数型
Everyday Life with clojure.spec
Everyday Life with clojure.spec
Lisp batton - Common LISP
Lisp batton - Common LISP
ATN No.2 Scala事始め
ATN No.2 Scala事始め
実践 Reactive Extensions
実践 Reactive Extensions
MlnagoyaRx
MlnagoyaRx
Ajax 応用
Ajax 応用
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming Paradigm
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
J qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているか
Xtext 紹介
Xtext 紹介
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Ext.directことはじめ
Ext.directことはじめ
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programming
VS勉強会 .NET Framework 入門
VS勉強会 .NET Framework 入門
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
Plus de fukuoka.ex
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
fukuoka.ex
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
fukuoka.ex
Elixir入門「第5回:Visualixirで見るマルチプロセス」
Elixir入門「第5回:Visualixirで見るマルチプロセス」
fukuoka.ex
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
fukuoka.ex
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
fukuoka.ex
AI入門「第1回:AIの歴史とTensorFlow」
AI入門「第1回:AIの歴史とTensorFlow」
fukuoka.ex
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
fukuoka.ex
Plus de fukuoka.ex
(7)
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
Elixir入門「第5回:Visualixirで見るマルチプロセス」
Elixir入門「第5回:Visualixirで見るマルチプロセス」
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
AI入門「第1回:AIの歴史とTensorFlow」
AI入門「第1回:AIの歴史とTensorFlow」
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
やや関数型を意識した風Elixir/Phoenixご紹介
1.
2017/07/12 (car (cdr ファンクション倶楽部))
LTエディション やや関数型を意識した風 Elixir/Phoenixご紹介
2.
1 そもそもElixirって どんな言語?
3.
2 1.Elixirは「データ変換」の言語
4.
3 1.Elixirは「データ変換」の言語 Elixirは、CSVファイルやDBデータ、JSON、バイナリデータ等の データを受け取り、パターンマッチし、加工・変換するのに適した、 動的型付けの関数型プログラミング言語です 上記の様々なデータフォーマットを、数値や文字列、リスト、マップ、 タプルに展開し、「パターンマッチ」でシンプルにコーディングできます なお、扱うデータは、全てイミュータブルです # iex iex> 1+2 3 iex>
list = [ 123, "abc", 456, true ] [123, "abc", 456, true] iex> map = %{ "key2" => "abc", "key1" => 123 } %{"key1" => 123, "key2" => "abc"} リストは[]で囲む マップは%{}で囲む 2種類書き方がある ①%{k1: "v1"…} ②%{"k1" => "v1"…} REPLでElixirコードを試せる
5.
4 1.Elixirは「データ変換」の言語:Enum Enumモジュールで、リスト/マップ/タプルが操作できます mapやfilter、reduce等、一通りあります iex> Enum.sort( list
) [123, 456, true, "abc"] iex> Enum.sort( map ) [{"key1", 123}, {"key2", "abc"}] マップをソートするとタプルに変換される (マップは順序を持てないため) iex> Enum.map( list, fn( x ) -> IO.puts( "value=#{x}" ) end ) value=123 value=abc value=456 value=true iex> Enum.filter( list, fn( x ) -> x >= 124 end ) ["abc", 456, true] iex> Enum.reduce( list, fn( x, pre ) -> "#{x}, #{pre}" end ) "true, 456, abc, 123"
6.
5 1.Elixirは「データ変換」の言語:パイプ パイプを使い、シェルのように、データを前から後ろに繋いで処理 できます (パイプ後の関数の第1引数に前の結果が渡される) この例はカンタン過ぎて、パイプの恩恵がイマイチ分かりにくいので、 中盤以降のコード例で、改めて紹介します # iex iex>
list = [ 123, "abc", 456, true ] iex> List.last( Enum.sort( list ) ) "abc" iex> list |> Enum.sort |> List.last "abc"
7.
6 1.Elixirは「データ変換」の言語:パターンマッチ パターンマッチは、Elixirの最もパワフルな一面です プロジェクト配下のファイルを以下のように編集して、実行します マップの”k2”キーの値抽出を、引数だけで実装できてしまいます # mix new
misc # cd misc lib/misc.ex mixというビルドツールでプロジェクトが作成できます defmodule Misc do def match_sample( %{ k2: value } ), do: value end # iex -S mix iex> Misc.match_sample( %{ k1: "v1", k2: "v2", k3: "v3" } ) "v2" iex -S mixでプロジェクトのビルドが走り、iexに入ります
8.
7 1.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" iex内でリビルドするときはrecompile()
9.
8 1.Elixirは「データ変換」の言語:パターンマッチ 該当キーがマップ内に存在しない場合、マッチエラーになります 引数に”_”を指定すると、その他としてマッチできるようになります 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: "-"}) iex> recompile() iex> Misc.match( %{ No: "-", NA: "N/A" } ) "Yes...NOT EXIST"
10.
9 1.Elixirは「データ変換」の言語:パターンマッチ もし、関数内でマッチさせるなら、以下のような書き方になります (ただ、関数の引数でマッチする書き方の方が推奨です) 実行結果は、引数パターンマッチ版と同じです defmodule Misc do def
match_in( input_map ) do %{ Yes: need } = input_map need end … iex> recompile() iex> Misc.match_in( %{ No: "-", Yes: "we can", NA: "N/A" } ) "we can"
11.
10 1.Elixirは「データ変換」の言語:パターンマッチ リストは、パターンマッチにより、「先頭」と「以降全て」で分割でき、 リスト要素の順次処理を組む土台となります 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] … iex> head4 [1] iex> tail4 []
12.
11 1.Elixirは「データ変換」の言語:パターンマッチ バイナリデータの分割/マップ化も、パターンマッチでとてもカンタン に書けます defmodule MP3 do defstruct
[ :header, :frames, :other_data ] def analisis( << tag :: bitstring-size( 24 ), version :: bitstrint-size( 16 ), flg :: bitstring-size( 8 ), size :: unsigned-integer-size( 32 ), data :: binary, # 以降のバイナリデータはここに集約される >> ) do %MP3 { :header MP3Header( tag, version, flg, size ) } end end
13.
12 1.Elixirは「データ変換」の言語:再帰(オマケ) ループは再帰で書きます (末尾再帰は最適化される) 処理対象が残っている間、繰り返される関数と、処理対象が無 くなった際の完了処理の2つの関数を用意し、パターンマッチに よって呼び分けが行われます なお、Enumとパターンマッチで大抵の事は済むので、再帰を書く 機会は結構少ないです defmodule Misc
do def nop( [ head | tail ], rows ), do: nop( tail, rows ++ [ head ] ) def nop( [], rows ), do: rows … # iex -S mix iex> Misc.nop( [ 5, 8, 3, 1 ], [] ) [5, 8, 3, 1] ※一応、for構文はあるけど使う場面はほぼ無い iex -S mixでプロジェクトのビルドが走り、iexに入ります
14.
13 1.Elixirは「データ変換」の言語:高階関数 高階関数は、3種類の書き方があります 「&」と「&n」で、「fn()」と「end」は省略可能です 関数後の「/n」で、「&n」すらも省略可能です iex> list =
[ 123, "abc", true ] iex> Enum.map( list, fn( x ) -> IO.puts( "#{x}" ) end ) 123 abc true iex> Enum.map( list, &IO.puts( &1 ) ) iex> Enum.map( list, &IO.puts/1 )
15.
14 2.【例】JSONパーサを作る
16.
15 Elixirのアプリケーション例として、Qiita API呼出と、返ってくる JSONのパースを行い、記事タイトルをリストアップしてみます 2.【例】JSONパーサを作る
17.
16 2.【例】JSONパーサを作る まず、ElixirのHTTPクライアント「HTTPoison」と、JSONパーサ 「Poison」を導入します 各モジュールは、ネットからインストールできます defmodule Crawl.Mixfile do … defp
deps do [ { :httpoison, "~> 0.7.2" }, { :poison, "~> 1.5" } ] end end # mix deps.get mix.exs
18.
17 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} 2.【例】JSONパーサを作る lib/crawl.ex
19.
18 2.【例】JSONパーサを作る StatusCodeが「200」のときだけ、Body部を抜き出します (この後、パターンマッチしやすいよう、Poisonでリストマップへの データ変換も行います) 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}}]
20.
19 作ったget()を見ると、変数で受け渡しがまどろっこしいです 一方、変数を無くすと、処理順と逆になるため、読みにくいです defmodule Crawl do def
get() do response = HTTPoison.get!( "https://qiita.com/api/v2/items?query= Elixir" ) body = body( response ) Poison.decode!( body ) end … 2.【例】JSONパーサを作る:パイプで書く defmodule Crawl do def get() do Poison.decode!( body( HTTPoison.get!( "https://qiita.com/api/v2/items? query=Elixir" ) ) ) …
21.
20 パイプで書くと、直感的かつスマートなコードとなり、ステキです defmodule Crawl do def
get() do "https://qiita.com/api/v2/items?query=Elixir" |> HTTPoison.get! |> body |> Poison.decode! end … 2.【例】JSONパーサを作る:パイプで書く
22.
21 タイトル抽出を追加し、URL周りをキレイにしたら完成です こんな感じで、たった11行のコードで、「Qiita APIを呼び、記事 タイトルをリストアップ」するアプリケーションが書けました 2.【例】JSONパーサを作る defmodule Crawl
do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> Enum.map( fn( %{ title: title } ) -> title end ) end def url( query ), do: "https://qiita.com/api/v2/items?query=#{query}" def body( %{ status_code: 200, body: json_body } ), do: json_body end iex> Crawl.get ["Advent Calendar 2016 投稿数の多いユーザランキング(上位50位)", "スタートアップ企業の技術選定でPhoenix(Elixir)&React(JS)+時々Echo(go)を採用した", "PhoenixでAPIによるログイン機能を実装する", …(他記事が複数並ぶ)… "Elixir/Phoenix環境をElasticBeanstalk Custom Platformで構築してみた"]
23.
22 コードを改めて見ると、メインの処理は、以下の流れを書き下した だけの形となっていて、直感的で分かりやすいコードとなっています URL →API呼出でJSON取得 →Body抽出 →JSONデコード →タイトル抽出 2.【例】JSONパーサを作る defmodule Crawl do def
get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> Enum.map( fn( %{ title: title } ) -> title end ) end def url( query ), do: "https://qiita.com/api/v2/items?query=#{query}" def body( %{ status_code: 200, body: json_body } ), do: json_body end
24.
23 3.応用:Qiita API以外のJSONパース
25.
24 3.応用:Qiita API以外のJSONパース Qiita API以外のAPIも、ほぼ同じコードでJSONパースできます 「はてなAPI」のJSONは、若干壊れている
(笑) ので、デコード 前に文字列操作で補正をかけるパイプを追加します defmodule Hatena do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> String.slice( 1..-3 ) # そのままだとinvalidなJSONなので加工 |> Poison.decode! |> Enum.map( fn( %{ title: title } ) -> title end ) end def url( query ), do: "http://b.hatena.ne.jp/entrylist/json?sort=count&url=#{query}" def body( %{ status_code: 200, body: json_body } ), do: json_body end # iex -S mix iex> Hatena.get ["【翻訳】超高速なJSON APIをElixirフレームワークのPhoenixでビ...", "2015/08/22/ElixirとPhoenixとMithrilのFFスタックでChatアプリを作っ...", …(他記事が複数並ぶ)… " Elixir ご紹介 // Speaker Deck"] lib/hatena.ex
26.
25 3.応用:Qiita API以外のJSONパース 「Wikipedia API」のJSONは、Qiita
APIより2段、深い階層 構造なので、titleを抽出できる階層まで下るパイプを追加します defmodule Wikipedia do def get( query "Elixir" ) do url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> dig |> Enum.map( fn( %{ title: title } ) -> title end ) 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 def body( %{ status_code: 200, body: json_body } ), do: json_body end # iex -S mix iex> Wikipedia.get ["熊沢千絵", "プログラミング言語一覧", …(他記事が複数並ぶ)… "エリクサー"] lib/wikipedia.ex
27.
26 3.応用:Qiita API以外のJSONパース 「Github API」は、検索パラメータの指定が異なるので、検索パ ラメータに渡すデフォルト値を変えます defmodule
Github do def get( query "Elixir-lang/Elixir" ) do # 例.rails/rails url( query ) |> HTTPoison.get! |> body |> Poison.decode! |> Enum.map( fn( %{ title: title } ) -> title end ) end def url( query ), do: "https://api.github.com/repos/#{query}/issues" def body( %{ status_code: 200, body: json_body } ), do: json_body end # iex -S mix iex> Wikipedia.get ["Use @optional_callbacks in GenServer", "Improve no function clause error messages", …(他記事が複数並ぶ)… "Make Mix more friendly for newcomers"] lib/github.ex
28.
27 4.高速WebFW「Phoenix」
29.
28 4.高速WebFW「Phoenix」 Elixirで組まれたWebFW「Phoenix」は、関数型でありながら、 Webページでのステートフルも持ち、Web+DBやJSON APIを コマンド5発で構築でき、高い性能と並行分散も備えています 0 10000 20000 30000 40000 50000 60000 Throughput (req/s) https://github.com/mroth/phoenix-showdown http://postd.cc/websocket-shootout Webページビュー性能比 WebSocket性能比 こんなWeb+DBのCRUD アプリが、テーブル構築も含め、 コマンド5発で生成できてしまう
30.
29 4.高速WebFW「Phoenix」 Phoenixは、Railsに似たビルドツールによる、Web (+DB)や JSON API
(+DB) の手軽な自動生成を実現しています (RailsのコミッターがElixirの世界に参入し、RailsライクなPhoenixをコミットしている背景があります) このコマンド5発で、Web+DBが、テーブルの構築も含め、実現 されます JSON API+DBの場合は、上記コマンド中、下記1行が異なる だけで、Web+DBとほぼ変わらない手順でJSON APIが構築 できます # mix phoenix.new web --no-brunch # cd web # mix ecto.create # mix phoenix.gen.html Post posts title:string body:text # mix ecto.migrate # iex -S mix phoenix.server DB追加 DBに「title」「body」列を持つテーブルを定義 (同時にModelやController、Viewも定義) DBへのテーブル構築とMVCモジュール生成 # mix phoenix.gen.json Post posts title:string body:text
31.
30 4.高速WebFW「Phoenix」 更に、Elixir構文のAltJS「ElixirScript」や、Haskellライクな 関数型AltJS「Elm」と組み合わせ、フロントサイドもサーバサイド も関数型なスタックを構成できます (ビルドツールも標準装備) Model Model Model 関数型でMVCライクな「Elmアーキテクチャ」
32.
31 5.副作用の分離
33.
32 UIやステート、DBといった副作用は、サーバプロセスとして分離 し、メッセージパッシングでget/setします 「生きているプロセス」に、値保持やIO処理を閉じ込め、ロック無 通信で高速にやり取りするイメージです たとえば、IO.puts()での画面表示は、「IOサーバプロセス」への メッセージパッシングが裏では走っています 5.副作用の分離 iex> IO.puts( "hoge"
) メッセージパッシング IO処理 IOサーバプロセス
34.
33 ステートは幾つかの実現法ありますが、最もシンプルなパターンの 「Agent」で作る例をQiita人工無能コラム#5で紹介しています 5.副作用の分離
35.
34 よりプリミティブなサーバプロセスとメッセージパッシングを作る例は、 Qiitaに入門スライドへのリンクと軽い解説あるので、ご覧ください (この続編と、OTP/Redisでの分散・耐障害を今月書きます) 5.副作用の分離