[Elixir in Action]Erlang/Elixirの再帰計算におけるnon-tail recursionとtail recursion

ちょっと印象的だったので。 再帰計算を行う関数の最後が、別の関数呼び出しかどうか、という違いです。 non tail recursion https://github.com/sasa1977/elixir-in-action/tree/master/code_samples/ch03 tail recursion https://github.com/sasa1977/elixir-in-action/blob/master/code_samples/ch03/sum_list_tc.ex Dive to source code Elixirには、再帰表現をまとめたコードとして Enum.reduce(collection, acc, fun) なんかを提供しています。 この中身を少しみてみましょう。 Elixirの の再帰箇所は以下のように書かれています。 Erlangの資料によると、 :lists.foldl(Fun, Acc0, List) はtail recursionとのこと。 こちら foldl/3 is tail recursive and would usually be preferred to foldr/3. ということは、 Enum.reduce(collection, acc, fun) はtail recursionなのですね。 コード追うと Enum.reduce/2 も Enum.reduce/3 を結局は呼ぶので、reduceはtail recursionで実装されていて、巨大なリストに対してもちゃんと再帰計算ができることを重視されているのですね。 Elixirの List.foldr/3 や List.foldl/3…More

[Elixir][Phoenix]簡単なWebアプリを生成してみた

やったこと備忘録。 最近、細々とElixir 1.0.5 x Phoenix 0.15.0ベースで、簡単な投票Webアプリケーションを作成してみました。 時間にして、作成自体、1日はいかない感じ。EctoやPhoenixを調べながらやって、1日といったところでしょうか。 使ってみた感想としては、PhoenxiはまんまRailsに近しいな、ということですね。 Railsに明るくなくとも、このくらいのアプリだとある程度書き進めることもできます。 ちなみに、私は明るくない側の人間です。 実装したことはこちら リポジトリはこちら Phoenixの他に、ログインなどの状態を保ちたいので、Guardianという認証ライブラリを使いました。 これ書いてて感じたのですが、文法的な表現は確かにElixirのように書くのですが、Supervisorなんかは別に書くわけではないし、なんかElixirを書いている!という感じがしなくもない… 最近Elixir in Actionを読んでいるのですが、ErlangからみたElixirという側面の強い情報を仕入れているのですが、なかなか面白いですね。学び始めて少しして、急にQiitaなんかでもやってみた系記事を見始めたのですが、それよりも前の古参の方々や学び始めた人、ここら辺を最初の一歩としてインプットしてるのかな。 Elixirのテスト関連を中心に色々知見を深めたい。More

[Elixir in Action]Read building blocks

Elixir in Action、Programming ElixirやGetting Startedなんかとは趣が異なって、BEAM VM上で動作するElixirという仕組みを色々深堀しているのですね。説明していること自体はかぶる箇所が多々あるのですが、より言語自体というよりも、その言語によって何を成すか?という目的に対してこの機能がある、といった感じで話が進んでいる感じ。 ところどころ、Erlang混じりの解説やリンクが登場するのはErlangを専門とする著者だから、の特徴かな。これ読んでいると、Erlangの言語的な表記というよりは、内部処理の知見もたまってくるという。 少し読んだところの特徴を抜粋。個人的なメモです。 Elixirは、moduleとfunctionに分けられる Elixirは純粋な関数型言語ではない。そのため、幾つか副作用がある関数が存在する。 データはimmutable。加工したデータは、異なるmemory locationに書き出される。ただし、shallow copyされたデータは共通の元となるデータをなるべく共有している。 booleanは true と false のatom nullabilityは無いので、 nil のatomを使う String typeは無い。binariesかlistで使う。 character listは、3-rd party製のErlangなんかが要求する時のみに使うことが良い。あとはbinary string使いましょう。 complex typeはlist、tuple、mapsだけ Range、Keyword list、HashDict、HashSetはデータシステムの元 keyword-listは値の小さな構造体で使う HashDictは、より大きなコレクションで性能を上げたい時に使おう HashSetはユニークな値の集合 & オペレータでlambdaを使おう Getting started では、 fn x -> function end を簡略化するために & を使ってましたね 粒度が結構違うメモなのですが、Elixirでの命名規則は以下の模様。 Elixirでの命名規則としての ?、! ? : true or false…More

[Elixir in Action]No technology is a silver bullet.

ここ最近、ざっとGetting startedやらexercism.io、PhoenixとElixirやその周辺ライブラリを触って、ちょっとしたライブラリも作って。Phoenix使って簡単なWebアプリ作って、というところをしました。 そんな折、Elixir in Actionを読み始めました。他のElixirの本も読もうと思うのですが、Actionシリーズなのでまずはこちらから読んでみようかな、と思いまして。 この書籍は言語自体の話から、Elixirのプラットフォームの話へと進んでいきます。多分、他の書籍も同じ。ただ、この書籍の著者はErlangを専門とする人のようで、RubyからElixirに寄った人たちとは異なった視点からの意見を望めます。良いですね。 Erlang Erlangの話から。Erlangはfault tolerance、Scalability、Distribution、Responsiveness、Live updateを重視した、高い可用性(high availability)を目指した言語です。それらを実現するための核が、concurrency。BEAM VM上に存在するプロセスとプロセス間通信を構築するなどでconcurrencyを核に添えた開発環境を構築できる、と。 WhatsAppsなんかはかなり有名ですね。私もErlangは少し触れたことがあります。ただ、言語の記述には慣れなかった… Elixir Elixirは、Erlangの記述を単純化したり、拡張することで描き易くしたものです。一言でいうとそんな感じなのですが、そこは開発者を取り込むために必要なものです。ClojurやRubyに影響を受けているので、そちら方面の人は馴染みやすそう。 No technology is a silver bullet. ErlangやElixirにも苦手なところがあります。この書籍では、その点も書いていて良かったです。 Speed: CやC++にはかないません。BEAM VMは、ハードウェア資源をめいいっぱい使うので、貧弱なハードウェアだと性能劣化が発生します。これは多くのプロセスを立ち上げ、処理を行っていくという特徴を持つから。なので、CPUの拘束が長い処理を行う場合、別の言語を選んだほうが良いでしょう。 Ecosystem: 単純に、まだ、エコシステムとしては小さい。 まだまだ先は長いですが、ちょっとづつ読んでいこう。 こういうfault toleranceなシステムや分散システムを前提としたシステムのテスト、品質(Quality)をどうやって評価するか、それをどうやって安定した開発に繋げることができるか?といったところ、テストエンジニアとして技術的な視点では非常に挑戦的で面白さを感じますね。 ただ、それらの先にユーザがいなければ自己満足な世界で終わるのでそこは忘れてはダメですね。More

[Elixir]Guardianでログインを固める on Phoenix

ちょっとしたWebサイトを作ろうとして、Elixirを最近触っていることもあってElixir x Phoenixで構築し始めている最近です。 その中で簡単なログイン機能を追加しようとしたところ、awesome-elixirにてGuardianなる開発途中の認証ライブラリを見つけました。開発者はRack Authenticationのwardenの開発者でもあるのですね。ほー。 試したのは、v0.5.0 Readmeを見ながら作業かなーと思っていたのですが、サンプル実装を公開していることを知り、まずはそこから動かしてみることにしました。 ただ、動かしてみるとPhoenixが0.13.1ベース。 私が今使っているのは0.15.0ベース。 …. ということで、サンプルをPhoenix 0.13.1ベースから0.15.0ベースに書き換えました。開発者の方へPRも投げたので、もしかするとマージされるかも。 変更ブランチはこちら https://github.com/KazuCocoa/phoenix_guardian/tree/upgrade_to_phoenix_015 差分はこちら https://github.com/KazuCocoa/phoenix_guardian/commit/c5bf0edf1fd64ecbf7d16ac0a45fb4f2fd10be6b 上記をcloneして以下の通りに実行すれば、Phoenix 0.15.0上でアプリを起動、ログイン試したり諸々できます。 主な修正はPhoenixの0.13.1=>0.14.0へのアップグレードガイド、0.14.0=>0.15.0へのアップグレードガイドをみるとわかるのですが、この例のChannelで使うSocket周りに破壊的な変更が入っているのと、controllerで :plug action を呼ぶ必要がなくなっているところです。 なんだかんだでこうやって簡単な例からコード追うと理解が進んで良いですね。 session管理の箇所とか、色々参考になりました。 作者が簡単な説明をこことかで説明しているので、そこをまず読んでみると良いかもしれません。あと、サンプル実装は mix phoenix.new で生成されたアプリをそのまま使っているので、差分をコードリーディングすると良さそう。 ちなみに、このサンプルアプリ、以下のようにsession情報を見ながら動作をみることができるので理解の助けになりそうです。 Rubyを継承してか?Elixir、なんかゲームみたいなライブラリ名が結構ありますね。More

[Elixir]パターンマッチやcase文でのwhenにおけるguard clauses

Elixirの記述に慣れるため、exercism.ioで簡単な問題を解きながら時間の合間に遊んでいます。 そこで少しエラーを何回も出してしまったのでメモ。 以下の通り、Elixirではguard clausesの中におけるbooleanの式ではand or not を使う必要があるみたいですね。 Note that while boolean operators such as and, or, not are allowed in guards, the more general and short-circuiting operators &&, || and ! are not. from: http://elixir-lang.org/getting-started/case-cond-and-if.html 他言語だとビット演算云々で私は || とか && を使うことに慣れていたのでつまづいてしまった… あと、同じように以下の[ここ]と書いている箇所。判定を読みやすくするために独自の関数を作ってみたのですが、guard clausesの中ではそのような独自な関数はちゃんとマクロ組んで作らないといけないのですね。 あらかじめこのwhenの中で使える関数が用意されていますが、それを超えるものはマクロ組んでいく必要があるみたい。ただ、それは可読性を損なう恐れのあるものなので、個人的には case example do のexampleをうまいこと表現したいですねー。 もう1個。以下のようなcaseを使った関数、パターンマッチを組み合わせた関数でも記述することができます。 case文 パターンマッチ whenの中に記述できる処理式には限りがあるので、複雑な分類であれば case を使うほうがよさそうですが、簡単な when で区分できる場合、関数自体を分けたほうが責務が明確になってよさそう。…More

[Elixir]パターンマッチにおけるpin演算子

個人的なメモです。 Elixirでの、pin演算子の意義として以下の返答をもらいました。 確かに、個人的に明示的にパターンマッチと知らせるために ^x = 1 のように書かせることに利点があるという言語設計、納得。More

[Elixir][Phoenix]has_oneやbelongs_toの関係にあるモデルを、他方のモデル生成時に合わせて生成する

has_one や belongs_to の関係になっているDeviceとUserのモデルを考えた時に、Device作成時にUserモデルも新規に作成したい時の話。 このメソッドは対象は、Phoenixのcreateリクエストを元にしています。 Rep.transaction とその中で依存性を持つ複数のDB処理を一括で書いています。 has_one や belongs_to の関係を持っているので、一方の _id に、もう一方の id を与える必要がある、ところがポイント。 もっとちゃんとした書き方あるのかな。ありそうな気がする。。。 この関係が正しくできているかは、controllerレベルでは以下のように適当なユーザを生成して、その上でindexなどが表示できることを確認すればOK。 この時、index.htmlでは device.user.user_name のような、has_oneの関係にある要素を描画しようとしていることが必要ですが。 Railsに似ているので、Railsも参考にしながら書いてみているけれど、DB周りの扱いがだいぶ想像できるようになってきた感じ。 まだ公開していないけれど、練習用repositoryはこちらMore

[Elixir]引数で与えられた関数を実行する

Elixirで、引数として関数 fn を与えた時、その与えられた関数を実行する方法がぱっと調べただけでは見つからなかったのでメモ。 以下のように、 f.() という形式で、与えられた引数としての関数を実施できるようですね。 簡単なサンプル もう少し進んで、exercismから同様な問題があったのでそれを使って見てみます。 テストコード 実行コード Rubyでいう、 yield を呼び出すのをElixirでは .() で行うのですね。 参考: http://hashrocket.com/blog/posts/elixir-functions-ruby-lambdasMore