Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Just an example of specialization in Elixir.
- #
- # I'm not sure if this pattern is a good practice in Elixir or
- # it's too much "OOP-like" and it would be more Elixirific to
- # use protocols. But using protocols to do the same thing would
- # probably lead to more boilerplate code (explicitly define all
- # funX in every protocol implementation).
- #
- # general base module
- defmodule ImplBase.State do
- defstruct base_data: nil
- end
- defmodule ImplBase do
- alias ImplBase.State
- defmacro __using__([]) do
- quote do
- def fun1(state) do
- #
- # NOTE: this is problematic - we DEMAND that all implementations' state data
- # allow Acces.get(data,:base_data)
- #
- # Or we could use some custom protocol to access base_data here but it's
- # almost the same situation...
- #
- IO.puts "fun1 - ImplBase implementation. data=#{inspect state.base_data}"
- state
- end
- def fun2(state) do
- IO.puts "fun2 - ImplBase implementation. data=#{inspect state.base_data}"
- state
- end
- defoverridable [fun1: 1, fun2: 1]
- end
- end
- @doc "Initialize ImplBase data"
- def init do
- %State{base_data: :some_base_data}
- end
- end
- # specific module no 1
- # - implementation without using any processes
- defmodule Impl1.State do
- defstruct base_data: nil, impl1_data: nil
- end
- defmodule Impl1 do
- alias Impl1.State
- use ImplBase
- @doc "Initialize Impl1 data"
- def init do
- %State{base_data: ImplBase.init, impl1_data: :some_impl1_data}
- end
- def fun1(s=%State{}) do
- IO.puts "fun1 - Impl1. data=#{inspect s}"
- s
- end
- end
- # specific module no 2
- # - implementation using Agent to store data
- #
- # NOTE: we have little problem here - we must use one data structure
- # as state wich allows Access.get(s,:base_data) and another
- # datastructure to be fed into Agent...
- defmodule Impl2.State do
- defstruct impl2_data: nil
- end
- defmodule Impl2 do
- alias Impl2.State
- use ImplBase
- @doc "Initialize Impl2 data"
- def init do
- {:ok,a} = Agent.start_link fn -> %State{impl2_data: :some_impl2_data} end
- %{base_data: ImplBase.init, agent: a}
- end
- def fun1(s=%{agent: a}) do
- data = Agent.get a, fn x -> x end
- IO.puts "fun1 - Impl2. data=#{inspect data}"
- s
- end
- end
- #
- # main
- #
- Impl1.init
- |> Impl1.fun1
- |> Impl1.fun2
- Impl2.init
- |> Impl2.fun1
- |> Impl2.fun2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement