TL;DR: Sharing and Reusing Functions in Elixir is easy. Unless its a Callback.

There’s a problem?

Using a public Elixir function defined in one module (e.g. DonorA) in another (e.g. Recipient1) is easy: just call it with the fully qualified name:

1
2
3
4
5
6
7
8
9
10
defmodule DonorA do
  def donor_a_fun_j do
    :donor_a_fun_j
  end
end
defmodule Recipient1 do
  def recipient_a_fun_p do
    DonorA.donor_a_fun_j
  end
end

Proof of the pudding:

1
2
3
test "test_donor_a_recipient_1_donor_a_fun_j" do
  assert :donor_a_fun_j = Recipient1.recipient_a_fun_p
end

Fine. Good. Job Done. End of Post. Thanks for reading.

No wait …

Read more


When I first started learning Elixir, I didn’t begin to appreciate the power of pattern matching until I’d read Sasa’s book and Dave’s book. Chapter 5 in Dave’s book had some really good prose explaining pattern matching the arguments of anonymous and (Chapter 6) named functions.

But it took me a while to assimilate what the Elixir (and Erlang) books were telling me, so I started writing my Elixir functions rather ignorant of how I could better structure them.

But as ignorance was displaced by experience with Elixir, I started to use pattern matching for functions all over the place, once I’d “seen” that many of my functions were variations (variants) on the same theme, really families of functions with the same purpose.

After a while of using bread’n’butter function matching, I found I’d developed a style of using pattern matching to create a DSL with its own set of verbs.

Then I’d write dsl programs using the verbs. Coffee anyone?

Read more


TL;DR: A macro to generate a Map API for a GenServer’s state or a Module with Agent-held state

The Trouble with State

Modules often need to keep state and share it but, as getting started says

Elixir is an immutable language where nothing is shared by default.

In Elixir there are two basic ways of sharing state: processes and ETS (which I wont consider further).

Arguably the most common way of implementing process-held state is GenServer. But for a module that does little more than hold state, GenServer can be overkill. As an alternative, an Agent provides a simpler, alternative way for a module to hold and manage its state.

But neither GenServer nor Agent provide any built-in API calls to manage the content of the state, not surprisingly as the state’s value can be anything.

More often than not though, I want the state to be a map, and sometimes with keys that are (sub)maps. So I usually want to make Map-like API calls — get, put, take, update etc — both for the state itself and any submaps.

Previously, I’ve written the wrappers manually. This is not hard but is just a bit tedious to do given the possible combinations of state wrappers, submap wrappers, arities, etc (lots and lots of cut’n’paste’edit!). So recently I’ve bitten the bullet and written a first cut of a macro to do the heavy lifting.

The interface I wanted for my applications’ modules was to simply use the module (that I’ve called Amlapio) that makes the API wrapper functions.

As many will already know use calls the __using__ macro in the module being used, and the code generated by __using__ is injected into the caller module.

Here’s an example (from the repo’s tests) of a module using an Agent to hold its state.

The wanted submap wrappers are defined by the agent: [:buttons, :menus, :checkboxes] option.

To generate state wrappers the submaps have been set to nil: agent: nil

Generating wrappers for only a subset of Map functions can be given using the funs options e.g, for the state wrappers, funs: [:get, :put, :pop]

Finally, a namer function has been given to name the state wrappers. It is passed two arguments: the map name (e.g. buttons for a submap, but nil for a state wrapper) and the Map function name (e.g. pop).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
defmodule ExampleAgent1 do

  # generate wrappers for three submaps
  use Amlapio, agent: [:buttons, :menus, :checkboxes]

  # generate *only* get, put and pop wrappers for the state itself and
  # use a namer function to name the wrappers "agent_state_get",
  # "agent_state_put" and "agent_state_pop"
  use Amlapio, agent: nil, funs: [:get, :put, :pop],
    namer: fn _map_name, fun_name ->
    ["agent_state_", to_string(fun_name)] |> Enum.join |> String.to_atom
  end

  # create the agent; note the default state is an empty map
  def start_link(state \\ %{}) do
    Agent.start_link(fn -> state end)
  end

end

These tests from the repo show how the submap wrappers would be used, pretty much how you’d expect. (The repo has tests for the state wrappers as well.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
test "agent_submap1" do

  buttons_state = %{1 => :button_back, 2 => :button_next, 3 => :button_exit}
  menus_state = %{menu_a: 1, menu_b: :two, menu_c: "tre"}
  checkboxes_state = %{checkbox_yesno: [:yes, :no], checkbox_bool: [true, false]}
  agent_state = %{buttons: buttons_state, 
                  menus: menus_state, checkboxes: checkboxes_state}

  # create the agent
  {:ok, agent} = ExampleAgent1.start_link(agent_state)

  # some usage examples

  assert :button_back == agent |> ExampleAgent1.buttons_get(1)
  assert :button_default == 
    agent |> ExampleAgent1.buttons_get(99, :button_default)

  assert agent == agent |> ExampleAgent1.menus_put(:menu_d, 42)
  assert menus_state |> Map.put(:menu_d, 42) == agent |> ExampleAgent1.agent_state_get(:menus)

  assert {[:yes, :no], agent} == 
    agent |> ExampleAgent1.checkboxes_pop(:checkbox_yesno)

end

Creating wrappers for a GenServer’s state is very similar. However, each wrapper has two “parts”: an api function and a handle_call function.

The api wrapper for e.g. `buttons_get/3` looks like this:

1
2
3
4
# api wrapper for buttons_get
def buttons_get(pid, button_name, button_default \\ nil) do
 GenServer.call(pid, {:buttons_get, button_name, button_default})
end

… while the matching handle_call looks like:

1
2
3
4
def handle_call({:buttons_get, button_name, button_default}, _fromref, state) do
  value = state |> Map.get(:buttons, %{}) |> Map.get(button_name, button_default)
  {:reply, value, state}
end

Here’s example of generating wrappers for a GenServer.

Remember: all handle_call functions must be kept together in the source else the compiler will complain.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
defmodule ExampleGenServer1 do

  # its a genserver
  use GenServer

  # generate API wrappers for three submaps
  use Amlapio, genserver_api: [:buttons, :menus, :checkboxes]

  # generate *only* get, put, pop and take wrappers for the state itself and
  # use a namer function to name the wrappers "state_get",
  # "state_put", "state_pop", and "state_take"
  use Amlapio, genserver_api: nil, funs: [:get, :put, :pop, :take],
    namer: fn _map_name, fun_name ->
    ["state_", to_string(fun_name)] |> Enum.join |> String.to_atom
  end

  # create the genserver; note the default state is an empty map
  def start_link(state \\ %{}) do
    GenServer.start_link(__MODULE__, state)
  end

  # << more functions>>

  # handle_calls start here

  # generate the handle_call functions for three submaps' wrappers
  use Amlapio, genserver_handle_call: [:buttons, :menus, :checkboxes]

  # generate the handle_call functions for the state wrappers.
  use Amlapio, genserver_handle_call: nil, funs: [:get, :put, :pop, :take],
    namer: fn _map_name, fun_name ->
    ["state_", to_string(fun_name)] |> Enum.join |> String.to_atom
  end

end

There are tests got the GenServer example in the repo but they look almost identical to the Agent example.

If you just want to give it a whirl, that pretty much it. Its available on Hex and just needs to be added to the dependencies in mix.exs in the usual way.

1
{:amlapio, "~> 0.1.0"}

But if you are interested in a high-level explanation of how I implemented Amlapio, read on.

Read more


TL;DR: Elixir - a language that positively celebrates the use of macros

I’ve been picking up some Elixir so I can try my hand at a new project I want to build using the Erlang/OTP ecosystem.

Elixir uses lots and lots of compile-time macros. The language’s pervasive use of macros is unprecedented in my experience. Most (all?) of the core features of Elixir (its special forms) are (non-overridable) macros (e.g. the case statement)

Everybody likes and wants to use a language that has macros. But you are not supposed to use them right? ☺ ☺ ☺

Possibly the single most comment that has endeared me to Elixir and its community is a passage from Chris McCord’s great book Metaprogramming Elixir.

Some of the greatest insights I’ve had with macros have been with irresponsible code that I would never ship to production. There’s no substitute for learning by experimentation.

Write irresponsible code, experiment, and have fun. Use the insight you gain to drive design decisions of things you would ship to a production system.

In the same vein as Chris’s just-give-it-a-go-and-learn-some-lessons meme, I recently watched Zack Tellman’s talk Some Things that Macros do at last year’s Curry On! where he made the point that macro usage in Clojure has tended to be either at the low-end, standard fare of boilerplate removal, or up at the high-end where the doyen of Clojure macros core.async towers. Zack reckoned the gap between the two extremes offered plenty of space for people to experiment with macros.

So, with that thought, this post is my first irresponsible experiment in designing, writing and using Elixir macros. Caveat Emptor

Read more


TL;DR: threading all the things

Update: 1Sep15

Whilst writing I discovered this post has not been updated after I’d received some feedback from Shaun Parker. No idea what happened. Sorry Shaun! You might want to jump straight to the “Update 1Sep15” section, and have a look at my some-as→ macro.

Introduction

The other day I was writing a Clojure let block to transform a map. It was a pretty usual Clojure pipeline of functions, a use case Clojure excels at. The pipeline included a cond, a couple of maps, some of my own functions, and finally an assoc and dissoc to “update” the input map with the result of the pipeline and delete some redundant keys.

Even though Clojure syntax is quite spare there was quite a bit of inevitable clutter in the code and it struck me the code would be cleaner and clearer if I could use the thread first (→) macro.

If you grok macros you can probably guess the rest of this post (likely you will have seen the title and probably said to yourself “Oh yeah, that’s obvious, nothing to see here” and moved along ☺ )

Read more