# Doctests: FTW!

I’ve been working on new releases of a couple of my published Hex packages recently, as well as some new packages that should be soon published fairly soon.

All of them have doctests, sometimes a lot of them.

I think doctests are great; I’m a fan. “But there’s a problem”

TL;DR: Code is Data!

# Backstory

Originally this post was part of another post. But the whole post was getting too big, so I’ve pulled it out here.

Although really just part one, its really stand-alone and may be of more general interest.

The repo has the examples.

# Metaprogramming with Macros

I guess anybody who knows anything, has read anything or used Elixir at all will be aware the core features of the language are implemented as a collection of macros – the special forms.

Elixir’s macro support is incredibly useful and I’d recommend anybody interested in learning some of the nitty-gritty to read Chris’s excellent book. Alternatively, there are also many excellent blog articles out there (like Sasa’s), and I’ve even had a go myself.

At the heart of macros are quoted forms, Elixir’s name for its abstract syntax tree (AST) representation.

When you run a macro, Elixir passes the arguments as quoted form(s) and expects quoted form(s) as the result (which will then be compiled). Inside the macro though, its just regular Elixir code, albeit manipulating ASTs.

I tend to think of the relationship (contract) between the Elixir compiler and a macro as simply this:

I’ll maybe pass you some asts, do what you want with them but give me back some asts and I’ll compile them for you.

But macros are not the only or best answer to some metaprogramming needs.

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:

Proof of the pudding:

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

No wait …

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?

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).

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.)

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:

… while the matching handle_call looks like:

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.

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.

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