Learning META-PROGRAMMING IN ELIXIR

Macroに関して学んだ。 quote で与えた文字列を Abstract Syntax Tree (AST) としてタプルで得ることができる。 unquote は、quoteで囲まれた中で使うことでquoteの中でunquoteした要素をinjectすることができる。 quoteやunquoteなどはこちらで確認可能。 他にもこちらとか。 defmoduleの中で @before_compile TestCase のように記述することで、コンパイル時にTestCase.__before_compile__/1を実施することができます。このようなModuleに対する定義は以下を参照すると良いとか。 http://elixir-lang.org/docs/stable/elixir/#!Module.html Getting Startedをすべて終えた… Macroなんかはまだ馴染まないとなーという感じですが、単純なコードは読み書きできてきた感じ。 ちょっとやりたいことがあるので、Phoenixのtutorialを読んでいこうかな。More

GimeiのElixir版を練習がてら書いてたらちゃんとしたものが公開された

まだElixirのチュートリアルをちゃんとやり始めて1週間くらいなのですが、ここ最近、Elixirを学んでみています。チュートリアルも終わり何か書きたいな、と思った時、Gimeiが他言語でポートされているブーム?みたくなっているぽいことを知りました。 ひとまず練習がてら同じようなものを実装しながら学ぼうと思い、以下のような練習リポジトリを作り、少しづつ手を動かし始めました。Hexで公開してからリポジトリを公開しようかなと思ってたのですが、作っている途中にちゃんと経験されている方が書いたgimeiのElixir版が出ていたのを昨日見つけたので、まだ全然途中で中途半端な感じなのですがprivateからpublicにしていいかなーというくらいのノリでリポジトリをpublicにしました。 もしElixirに興味のある方は、後者のgimei_exを使いましょう。 私のやつ https://github.com/KazuCocoa/elixir-gimei ちゃんとしている方 https://github.com/ma2gedev/gimei_ex 私のリポジトリは機能的にもまだ未完全です。また、DocTestを使ってみたりと違ったこともしています。これからも多分色々TODO増減しながら試していきそうです。Hexにあげるまではしてみたいな。 Erlangのライブラリ探して使ったり、関数型のような記述をしたり。まだ手続き型の考えのほうが強いですが、caseやrecursiveな書き方は、Elixirは好きな感じです。Elixir学んでいるとErlangも学ぶこともできるという特典付き。 ともあれ、こういう新しいものを学んで世界を広げるって、良いですね。More

MIX AND OTP vol 2

Mix and OTPの後半。 ETS ここは、GenServer、Supervisor付近の説明から。 リンク http://elixir-lang.org/docs/stable/elixir/#!GenServer.html http://elixir-lang.org/docs/stable/elixir/#!Supervisor.html ソースコードは以下 https://github.com/elixir-lang/elixir/blob/v1.0.4/lib/elixir/lib/supervisor.ex processによる状態の保持と、etsによる保持はいくつか違うところがあります。 processに状態を保持する場合、そのprocessが死んだらそれに保存されるデータも無くなります。一方、etsは複数のprocessに共有されるキャッシュのように扱うことができます。 共有キャッシュのように扱うことができるので、etsに対しては書き込み制限をしたりします。また、callbackに関しても同期的に行う必要がるなどの制約がでてきます。 ここら辺の説明がされますが、etsを生成したprocessが死んだ場合、etsも合わせて自動的に閉じられます。これは、etsはそれを起動したprocessにリンクされているから。 ということは、supervisorで起動させて、publicにするとprocessに依存して、それが死ぬとetsが閉じられるという事態も回避できそうです。 このページの最後の箇所の、 :ets.foldl() のfnへの引数で、 {name, pid} が与えられているのですがこれがどこから来たのかよくわからなかった… のですが、 の所を見て納得。 :ets(table) に保存していた値がfnの引数として与えられ、それに対して関数が適用されて出力が得られるというものなのですね。説明にもさらりと描かれているのですが、initの中に突然nameとpidが出てきたので???になりました。 このfoldlのErlangによるspecは以下。 pipelineでメソッドチェインぽく描くとき、 () はsつけるべきなのですね。そのほうが意図が伝わるコードになりますし。引数の数が違う同名の関数もあるので、これはすごく納得。 なるほどなるほど。 Task and gen-tcp Taskは、非同期に処理を行うprocess。 processなので、そのprocessを監視するためにsupervisorへの登録が大事になってくるのですが、そこの詳しくはTask.Supervisorをみると良さそう。 こうざっと読んでみると、Supervisorが非常に重要な位置をしめて、そのsupervisorが監視する子プロセスへの再起動strategyも大事。これらがErlangというかElixirの安定性を支えているのですね。 結構、Unit testでロジックをしっかりかかないと、ここはdebugとかスキル必要そうだ。。。 Docs, tests and pipelines ExUnit.DocTest、半端ない。ドキュメントがそのままiexのコマンドベースでのテストコードに置き換わるのですね。 http://elixir-lang.org/docs/stable/ex_unit/#!ExUnit.DocTest.html 例えば、以下の@docで囲んだドキュメントになる範囲の iex> とその次の行がコマンドと期待結果になって、テストが実施される。APIとして目に見えるインタフェースでは、このテストかなり役立つのでは。autodocみたいなものですね。 ここは、最後はどのようなテストコードを作っていくか、というのも含め、戦略はチームで形作っていく必要あるよね、ってもので終わってました。 Distributed tasks and configuration 最後は、異なるノード間での通信が話題です。ネットワーク越しに異なるノード間で通信をやりとりし、一方から送った処理をもう一方のノードで実行するということが可能です。 Node.spawn_link/2 を使うのですが、普通に使うとsupervisorの管理下に置くことができないので、以下の3通りが紹介されています。…More

MIX AND OTP vol 1

ElixirのGetting startedも、Mix and OTPの話に入りました。 http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html でつくられる各ファイルの説明などから始まり、実際にExUnitでテストを書くまでの説明が載っています。 Agent Elixirはimmutable languageなので、状態を保持するにはProcessesかETS(Erlang Term Storage)を使う必要があります。ここは、Getting StartのところのProcessやTaskのところで説明があった、TaskとかAgentの話ですね。 ExUnit setup が用意されているのだけれど、このsetupのcallbackが後の test へ渡されるらしい。なので、setupで最後に渡す引数を渡して、それを test で受け取らないといけないのですね。 setupやsetup_allがあれば、teardownに該当するものもあるのかな?と思ってみると、 on_exit があるのですね。 ExUnit.Callbacksの中に、以下のような定義がありました。 これは ExUnit.OnExitHandler をcaseで呼んで使っている模様。 また、このon_exit自体はaddされるだけなので、ExUnit.OnExitHandlerのもとがどこにあるかコードで追ってみると、最終的には ExUnit.Runner の run の中にある loop に行き着いた。この処理開始のときに、 ExUnit.OnExitHandler も登録されて処理が進み、 on_exit でOnExithandlerにfnを登録、テストケースが終わった時点で実行する、と。なるほど。 もう少し、ExUnitを遡ると、ExUnit のモジュールでstart/1が定義されていて、その中の System.at_exit にテストケースが登録されていることが一番の始まりみたい。 ちなみに、この at_exit の説明は以下。 Registers a program exit handler function. Registers a function that will…More

Get start Elixir vol 3

Sigils Elixirでは、正規表現を書くときに ~r/neko/ と書きます。その ~r の書き方箇所のバリエーションや、 ~w 、 ~W などのword list、カスタムsigilsの作り方が書いていました。Rubyでも%wといったものをよく使うので、こちらも使いそうですね。 try, catch and rescueの使い方 In Elixir, we avoid using try/rescue because we don’t use errors for control flow. We take errors literally: they are reserved to unexpected and/or exceptional situations. In case you actually need flow control constructs, throws should be used. That’s what…More

Get start Elixir vol 2

processのところから、protocolのところまで。 processの話の中で、以下の文言がありました。 Process and links play an important role when building fault-tolerant systems. In Elixir applications, we often link our processes to supervisors which will detect when a process dies and start a new process in its place. This is only possible because processes are isolated and don’t share anything by default. And if processes…More

再帰的な書き方に頭が馴染んできた: Elixir

exercismでElixirの問題を解いていた時、いろいろなるほどなーと面白かったのでメモ。 仕様は、入力(sentence)に対して単語区切りごとに、sentence全体の文字をキーに含まれる文字をカウントする、というもの。 例えば、 “abc de fge” を入力とすると、abc、de、fgeがそれぞれ1つづつ存在するとカウントする。 “abc de abc” を入力とすると、abcが2つ、deが1つ存在するとカウントする、というもの。 Elixirだと、繰り返しは再帰的に書く。数列的な書き方になるので、少し頭になじませる時間が必要でしたが、再帰的な書き方に考えが馴染むと数学のようにかけて、個人的には書きやすかったです。プログラムだと手続き型に慣れていたけれど、関数的にかけると数学的な考え方をそのまま残せるのが良いですね。 これを、さらにreduceを使って書いてみます。 Elixir1.0.4におけるreduceの説明は以下。 Elixir、なるほどね。More

Get start Elixir vol 1

Elixir自体に慣れようと、Get startedをなめてみました。Elixir 1.0.4がリリースされた頃のものです。以下はメモがてら、です。 http://elixir-lang.org/getting-started/introduction.html すごくDocumentが整備されている感がありました。 特に繰り返しでは再起を使うというRecursionの説明があったあと、それを容易にするための Enum を提供しててその機能に関する説明、 Stream の話もという形で頭にストーリーを植え付けながら内容を理解できる感じです。 以下、ちょっとメモです。 Modules http://elixir-lang.org/getting-started/modules.html でコンパルしたとき、 を実行したディレクトリと同じディレクトリにコンパイルしたものがあれば、自動的に読み込まれてりようできるもよう。 はスクリプトとして実行される。 defpは、同一モジュール内からのみ呼ぶことが可能なprivateなモジュール。なるほど。継承とかどうなのかな。(まだそこらへんは読んでない。 defoverridable で提供されているらしい?めも) Recursion http://elixir-lang.org/getting-started/recursion.html 再起でforを実現するのは関数型っぽくて頭になじまないと厳しそう。ただ、ここら辺は大学とか含めて数学的な素養を学んだ人からすると、慣れるまでに時間もかからなさそう。数列の世界の話みたいなものですしね。 Enum のライブラリにいくつかあらかじめライブラリが用意されているので、それは便利。ちょうど次の章で説明されていた。 http://elixir-lang.org/getting-started/enumerables-and-streams.html EnumとStreamを比較しながら話が進んでいて、StreamはLazyというところが違うと書いていた。 Enumは常にEnumの実際の値を返すけれど、Streamは必要なときに実際の値を返すがそれまではStreamとして保持している、と。 Pipeoperatorの対比を見ればおおー、なるほどという感じだった。 Pipeoperatorのときは基本Stream使っていって、lazinessが必要な大きなデータを扱うようなときとかコレクションを使ったりするときはEnumを使っておけば良い、という感じかな。 チュートリアルでの最後の締めは以下。 The amount of functions and functionality in Enum and Stream modules can be daunting at first but you will get familiar with them case by…More