スポンサーリンク

2016年5月11日

[Elixir]Play with the defdelegate

とある錬金術師の万能薬(Elixir)

Goal

  • defdelegateで標準のモジュールを利用する
  • defdelegateで自作のモジュールを利用する

Dev-Environment

  • OS: Windows8.1
  • Erlang: Eshell V7.3, OTP-Version 18.3
  • Elixir: v1.2.3

Play with the defdelegate

まずは標準で用意されているモジュールをデリゲートで使ってみる。
今回は、Enumのreverseをデリゲートで使ってみよう。

File: delegate_sample.ex

defmodule DelegateSample do
  defdelegate reverse(enumerable), to: Enum
  defdelegate other_reverse(enumrable), to: Enum, as: :reverse
end
  • “to:”でデリゲートしたいモジュールを指定する
  • “as:”でデリゲートする関数を別名で使う場合に元となる関数を指定する

Note:

非推奨(?)になるみたいなので、"append_first:"オプションは割愛しています。

参考: http://d.hatena.ne.jp/hayabusa333/20160116/elixir_changes_20160115
参考: https://github.com/elixir-lang/elixir/issues/4199

Example:

iex> DelegateSample.reverse([1,2,3])
[3, 2, 1]
iex> DelegateSample.other_reverse([1,2,3])
[3, 2, 1]
無事実行できました。
続けて、自作のモジュールをデリゲートで使ってみたいと思います。

File: sample.ex

defmodule Sample do
  def sample do
    IO.puts "sample"
  end
end

File: delegate_sample.ex

defmodule DelegateSample do
  ...

  ## My Module
  defdelegate sample(), to: Sample
  defdelegate other_sample(), to: Sample, as: :sample
end

Example:

iex> DelegateSample.sample
sample
:ok
iex> DelegateSample.other_sample
sample
:ok

Note:

defdelegateはpublic扱いになる。
そのため、privateで使いたいのであればimportで対応をする。
複数のデリゲートを一度に定義はできるのでしょうか?
検証してみましょう。

File: sample.ex

defmodule Sample do
  ...

  def sample2 do
    IO.puts "sample2"
  end

  def sample3 do
    IO.puts "sample3"
  end
end

File: delegate_sample.ex

defmodule DelegateSample do
  ...

  defdelegate [sample2(), sample3()], to: Sample
end

Example:

iex> DelegateSample.sample2()
sample2
:ok
iex> DelegateSample.sample3()
sample3
:ok
問題なく定義できるみたいです。
もう一つ検証してみましょう。
別名は一度につけられるのか?(これは無理だと思いますが・・・)

File: delegate_sample.ex

defmodule DelegateSample do
  ...

  defdelegate [other_sample2(), other_sample3()], to: Sample, as: :sample2, as: :sample3
end
うん、まぁコンパイルは通りますよね。
記法上間違いがあるわけじゃないですし。

Example:

iex> DelegateSample.other_sample2()
sample2
:ok
iex> DelegateSample.other_sample3()
sample2
:ok
実行はできるけど、sample2/0の方が実行されてしまったみたいです。
以上!
誰かの役に立ったなら幸いです。m( )m

Bibliography

2016年5月10日

[Elixir]Play with the Elixir-Macro

とある錬金術師の万能薬(Elixir)

Goal

  • マクロのさび落とし
  • 見た目の記法だけChankoっぽいもの(偽物)を実装する(内部実装は・・・)

Dev-Environment

  • OS: Windows8.1
  • Erlang: Eshell V7.3, OTP-Version 18.3
  • Elixir: v1.2.3

Play with the Elixir-Macro

A/Bテストをやろうと思っていたのに、気が付いたらマクロでやっていました。
(機能の一部で)見た目の記述だけChankoっぽいもの(完全な偽物)を実装してみました。
あくまで使うときの見た目だけなので、実装に関しては残念ながら微妙です。
結局、内部でtry~rescueとifを使って処理しています。
本気でやるならブラッシュアップが必要ですね。
最初のとっかかりとしては、まぁこんなもんでしょう。(残当)
それでは、やっていきます。

Module: Unit

テスト用のモジュールで使うマクロを定義したモジュールです。
  • active_if/1: 実行するのかしないのかのフラグを返すだけの関数をマクロで展開しているだけです。
  • function/2: 関数を動的にマクロで展開しているだけです。func_nameが関数名になります。

File: unit.ex

defmodule Unit do
  defmacro __using__(_options) do
    quote do
      import unquote(__MODULE__)
    end
  end

  defmacro active_if(condition) do
    quote do
      def active? do
        unquote(condition)
      end
    end
  end

  defmacro function(func_name, clauses) do
    if func_name do
      quote do
        def unquote(String.to_atom "#{func_name}")() do
          Keyword.get(unquote(clauses), :do, nil)
        end
      end
    end
  end
end

Module: TestControllerUnit

サンプルとしてUnitモジュールを使ってみたモジュールです。
Unitモジュールを実際に使ってみるとこんな感じになります。

File: test_controller_unit.ex

defmodule TestControllerUnit do
  use Unit

  active_if true

  function(:show) do
    d = 5
    e = d + 6
    f = e + 7
  end
end

Module: Helper

補助関数を定義しているモジュールです。
  • exec/2, exec/3, atom_to_module_string/1: モジュールがatomのままだとapplyで実行できないため、補助関数として作りました。

File: helper.ex

defmodule Helper do
  def exec(module, fun) do
    exec(module, fun, [])
  end
  def exec(module, fun, []) do
    atom_to_module_string(module) |> String.to_atom |> apply(fun, [])
  end
  def exec(module, fun, args) when is_list(args) do
    atom_to_module_string(module) |> String.to_atom |> apply(fun, args)
  end

  def atom_to_module_string(atom) do
    "Elixir." <> (Atom.to_string(atom) |> Mix.Utils.camelize)
  end
end

Module: Invoker

結局、内部でtry~rescueとifを使って、
実コードにてマクロが展開されているだけになってしまいました。
  • invoke/3: テスト対象のモジュールと関数を指定して、デフォルトの処理をdo~endで記述する。

File: invoker.ex

defmodule Invoker do
  defmacro __using__(_options) do
    quote do
      import unquote(__MODULE__)
      import Helper
    end
  end

  defmacro invoke(module_name, func_name, clauses) do
    quote do
      do_clause = Keyword.get(unquote(clauses), :do, nil)

      try do
        if exec(unquote(module_name), :active?) do
          exec(unquote(module_name), unquote(func_name))
        else
          do_clause
        end
      rescue
        _any -> do_clause
      end
    end
  end
end

Module: TestController

サンプルとしてInvokerモジュールを使ってみたモジュールです。
Invokerモジュールを実際に使ってみるとこんな感じになります。

File: test_controller.ex

defmodule TestController do
  use Invoker

  def show do
    invoke(:test_controller_unit, :show) do
      a = 1
      b = a + 2
      c = b + 3
    end
  end
end

Example:

## active_if: true
iex> TestController.show
18

## active_if: false
iex> TestController.show
6
TestControllerUnitでraiseを起こしてみると、rescueの処理が実行される。

Example:

defmodule TestControllerUnit do
  ...

  function(:show) do
    d = 5
    e = d + 6
    raise "oops"
    f = e + 7
  end
end
iex> TestController.show
6
もう少しtry~rescueやifのあたりを何とかしたかったのですが、
マクロの動作に翻弄されて、そこまで手が回りませんでした。
あまり参考になるコードではないと思いますが、誰かの役に立ったなら幸いです。m( )m

Bibliography

2016年5月5日

What is A/B-Test?

Goal

  • A/B-Testについて調査する

Dev-Environment

  • OS: Windows8.1

What is A/B-Test?

A/Bテストをやりたいと思いました。
しかし、A/Bテストと言うものをよく知らない(笑)
そういうわけで知らないなら調べればいいじゃない!
今回は、A/Bテストについて調べた調査記録と言うことになります。
テストについて素人以前の人物がまとめた内容になりますので、
ご指摘等あると思います。その際はコメントにてご教授いただけると幸いです。

A/B-Test is 何?

A/Bテスト・・・それは可能性の検証・・・って書くと少しかっこいい気がする(笑)
下らない妄言は置いておくとして、早速本題に入りましょう。

A/Bテストとは、2つある選択肢のうち、どちらが良い結果をもたらすか見極めること。

別名としてスプリットテスト、スプリットランテストとも言う。(個人的にはこちらの方が好き)

※AとB以外にもテストを用意して行うのは多変量テストと呼ばれている
色々なサイトを見て大体どこにも載っていたの内容があった。

「小さく始める」

なんだが、マイクロサービスやスクラムのようですね(笑)
実際、ある重要な業務においてやったこともない人をいきなりアサインするでしょうか?
いや、しませんね・・・少なくとも私はそうします。もし新しい人を導入するなら小さく補助付きでやらせます。(状況が許せば)
それと同じく、サイトの重要な部分にいきなり着手するのではなく、
ごく些細な部分から始めていくことが大事なようです。
これには別の意味もあると思います。
それは、まず効果を観測/測定すると言うことです。
効果をデータとして出力され観測/測定してから、追加でテストをしていくと言うことですね。

A/B-Test の Point

  • AとBにおける要素の違いを明確にする
例) 女性と男性でメッセージを分けるなど
  • テスト対象とするユーザの条件を明確に分類し行う
全てのユーザに行っても正確なデータが取れるか分からないし、
データを取得するためにかかる時間も多くなるでしょう。
A/Bテストを行うための格言

辛抱強く数%の小さい改善を繰り返し、最終的に数十%の効果にする

つまり忍耐強く耐えましょうってことですね。
すぐには効果が出るかは分かりません。
そのため、単発で終わらせてはいけないと言うことです。
  1. 部長を説得してA/Bテスト導入
  2. しかし、あまり効果は上がらない・・・
  3. 部長「効果が出ないじゃないか、これは意味がないな中止しろ」
  4. A/Bテスト終わり
これはダメですね(笑)
そも前提として、本当に導入する意味はあるのか?っという問題もあるでしょうが・・・

取りとめもない独り言

単純にやるだけなら簡単だと思います。(実際、ツールやライブラリは探せば割とすぐ発見できます)
しかし、効果を出そうとするのが難しいのは別の要因があると思います。
意思決定と同じで評価基準となる部分が話を難しくしているのだと考えます。
データとして結果が出た・・・でも、その解析を間違えていたら?
AとBを用意した・・・それは本当に意味のあるAとBですか?
辛抱強く改善を繰り返していける環境なのか?
などなど、プログラムの部分ではないことが多いのではないかと感じました。
効果や分析については、あらかじめ本や論文で勉強し、
効果のあるパターン(?)のようなものを学ぶのが手っ取り早いと思います。
職場環境、人間関係は・・・私があまりコミュニケーション能力ないので、なんとも言えませんね。(汗)
以上、少しでも誰かの参考になったら、この上ない喜びです><

Bibliography

人気の投稿