Let’s walk through the process of writing and publishing an Elixir
library from start to finish. For illustrative purposes, we’ll create a pretend simple_statistics
statistics toolkit for Elixir.
Note: if you need an actual statistics library check out
statistics
.
The full source code is available on Github.
Create an Elixir Project
$ mix new simple_statistics
$ cd simple_statistics
$ mix test
Mix will generate the following directory structure:
|-- _build
|-- config/
|-- config.exs
|-- lib/
|-- simple_statistics.ex
|-- test/
|-- simple_statistics_test.exs
|-- test_helper.exs
|-- mix.exs
|-- mix.lock
|-- README.md
|-- .gitignore
Write Code
You can create a new folder in lib/
with the name of your package (simple_statistics
) to place other modules. It’s a good idea to split code to different modules for modularity. We’ll create a new lib/mean.ex
module.
|-- lib/
|-- simple_statistics/
|-- mean.ex
|-- simple_statistics.ex
# lib/simple_statistics/mean.ex
defmodule SimpleStatistics.Mean do
def mean([]), do: nil
def mean(list) do
Enum.sum(list) / Kernel.length(list)
end
end
Write Documentation
Use @doc
to specify docstrings. You should ideally document every major public function in your modules:
# lib/simple_statistics/mean.ex
defmodule SimpleStatistics.Mean do
@doc ~S"""
The mean is the sum of all values over the number of values.
"""
def mean([]), do: nil
def mean(list) do
Enum.sum(list) / Kernel.length(list)
end
end
Add Doctests
You can add doctests
in your docstrings like so:
# lib/simple_statistics/mean.ex
defmodule SimpleStatistics.Mean do
@doc ~S"""
The mean is the sum of all values over the number of values.
## Examples
iex> SimpleStatistics.Mean.mean([])
nil
iex> SimpleStatistics.Mean.mean([1,2,3,4,5])
3.0
iex> SimpleStatistics.Mean.mean([1.5,-2.1,3,4.5,5])
2.38
"""
def mean([]), do: nil
def mean(list) do
Enum.sum(list) / Kernel.length(list)
end
end
To run them as part of your test suite:
# test/simple_statistics_test.ex
defmodule SimpleStatisticsTest do
use ExUnit.Case
doctest SimpleStatistics.Mean
end
$ mix test
.
Finished in 0.07 seconds (0.07s on load, 0.00s on tests)
1 test, 0 failures
Add Type Annotations
We can use Typespecs to utilize static type checking for our functions:
@spec mean(nonempty_list(number)) :: float()
def mean(list) do
Enum.sum(list) / Kernel.length(list)
end
Typespecs helps ensure that there’s no discrepancy between differing types of our program’s constants, variables, and functions.
You can then perform static analysis by using dialyzer
. First, update your mix.exs
to add dialyxir as a dependency:
defp deps do
[{:ex_doc, "~> 0.11", only: :dev},
{:earmark, "~> 0.1", only: :dev},
{:dialyxir, "~> 0.3", only: [:dev]}]
end
Then, run dialyzer
- Erlang’s static analysis tool:
$ mix dialyzer
Starting Dialyzer
dialyzer --no_check_plt --plt /Users/yosriady/.dialyxir_core_18_1.2.0.plt -Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspecs /Users/yosriady/simple_statistics/_build/dev/lib/simple_statistics/ebin
Proceeding with analysis... done in 0m1.68s
done (passed successfully)
Generate Documentation
Update your mix.exs
to add the following dependencies:
defp deps do
[{:ex_doc, "~> 0.11", only: :dev},
{:earmark, "~> 0.1", only: :dev}]
end
Then, run:
$ mix docs
$ cd docs
$ open index.html
Here is the live documentation, hosted on Github Pages.
As you can see, our documentation also displays docstring examples as well as any type annotations. Cool!
Publishing your Library
We’re now ready to start publishing our library.
Register with Hex
First, you need to set up an account on Hex, Erlang and Elixir’s package manager:
$ mix hex.user register
Click on the email confirmation link to activate your Hex.pm acccount.
Set your project’s metadata
Update your mix.exs
:
# mix.exs
def project do
[app: :decision_tree,
version: "0.0.1",
elixir: "~> 1.2",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
description: description,
package: package,
deps: deps]
end
defp description do
"""
A few sentences (a paragraph) describing the project.
"""
end
defp package do
[
files: ["lib", "mix.exs", "README.md"],
maintainers: ["Yos Riady"],
licenses: ["Apache 2.0"],
links: %{"GitHub" => "https://github.com/Leventhan/simple_statistics",
"Docs" => "http://hexdocs.pm/simple_statistics/"}
]
end
After the package metadata and dependencies have been added to mix.exs
, we are ready to publish the package with the mix hex.publish
command:
$ mix hex.publish
Publishing simple_statistics 0.0.1
Dependencies:
Files:
lib/simple_statistics.ex
lib/simple_statistics/mean.ex
mix.exs
README.md
App: simple_statistics
Name: simple_statistics
Description: Statistics toolkit for Elixir.
Version: 0.0.1
Build tools: mix
Licenses: Apache 2.0
Maintainers: Yos Riady
Links:
Docs: http://hexdocs.pm/simple_statistics/
GitHub: https://github.com/Leventhan/simple_statistics
Elixir: ~> 1.2
WARNING! Excluded dependencies (not part of the Hex package):
ex_doc
earmark
dialyxir
Before publishing, please read Hex Code of Conduct: https://hex.pm/docs/codeofconduct
[#########################] 100%
Published at https://hex.pm/packages/simple_statistics/0.0.1
Don't forget to upload your documentation with `mix hex.docs`
Note that this will be published as the version specified in mix.exs
.
A published version can be amended or reverted with
--revert
up to one hour after its publication. If you want to revert a publication that is more than one hour old you need to contact an administrator.
Publishing Documentation
You can publish your documentation to Hex Docs. The documentation will be generated by running the mix docs
task.
$ mix hex.docs
Docs successfully generated.
View them at "doc/index.html".
[#########################] 100%
Published docs for simple_statistics 0.0.1
Hosted at https://hexdocs.pm/simple_statistics/0.0.1
See the live documentation.
This documentation will be accessible at https://hexdocs.pm/my_package/1.0.0
. In addition, https://hexdocs.pm/my_package
will always redirect to the latest published version. Instead of Hex.pm, you can alternatively host the documentation at docs/
yourself or on Github Pages.
Appendix: Versioning
Publish a new version by updating the version
value in mix.exs
and running mix hex.publish
.
Remember to use Git tags to annotate version changes!
$ git tag -a v0.0.1 -m "Version 0.0.1"
$ git push origin v0.0.1
In Closing
We’ve succesfully written and published an Elixir library! Writing and publishing libraries in Elixir is easy and straightforward. Other developers can now add your library into their deps
and start using it in their projects.
Thanks for reading! Let me know if you have any feedback in the comments below.