This article is participating in a contest from Wunsh.ru - the Russian-speaking community of Elixir. Practices and just sympathizers - join us !
I am writing this article in order to consolidate the knowledge gained in the process of learning the language Elixir and its infrastructure. I hope that this article will be useful to programmers who decide to write Elixir applications.
"Elixir is a dynamic, functional programming language designed to create scalable and easily supported systems." - elixir-lang.org
Using Elixir to create your applications you will definitely come across Mix. It will become your indispensable assistant, because through it you will be able to execute such commands as creating, building, testing and publishing applications, as well as managing dependencies and much more. If you are familiar with Ruby, this tool is very similar to Bundler, RubyGems and Rake combined. In a nutshell, Mix is a handy tool that comes with Elixir and performs as many tasks as a Swiss knife.
The easiest way to create a template for your future mix application is using the 'mix new app_name' command.
$ mix new quadratic_equation
This command will create a kind of skeleton of your application. Namely, the folder with the name quadratic_equation and the following file and folder structure:
.gitignore # README.md # markdown config/ config.exs # lib/ quadratic_equation.ex # mix.exs # mix- c test/ quadratic_equation_test.exs # test_helper.exs #
There are several file naming conventions that you might need to know:
Observe the adopted structure in the applications, and this will allow the compiler to download the code without unnecessary errors.
To place the tests when generating a new mix-application, the test/
folder was created. Testing an application is an important (but not integral) part of writing workable (but not necessarily quality) code.
The tests are run using the mix test
command from the application root folder, for more informative output the option - --trace
is --trace
.
$ mix test --trace
Also the option --trace
makes sense to use when your tests block each other. The option will also make the launch of all tests synchronous (will cancel the action async: true).
This command will also create the _build
folder and compile your application into it in a test environment by placing all .beam
files.
iex is the online application console supplied with Elixir. Regarding Ruby, this is analogous to irb.
You can start the mix application using the iex -S mix
command. This command will precompile your code if required and launch the interactive console by loading your application into it.
$ iex -S mix Erlang/OTP 19 [erts-8.1] [source-e7be63d] [64-bit] [async-threads:10] [hipe] [kernel-poll:false] Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help) iex(1)>
You can compile your application separately using the command mix compile
.
Due to the simplicity of the application, we will place all the code in the body of the top-level module, namely in QuadraticEquation.
# lib/quadratic_equation.ex defmodule QuadraticEquation do @moduledoc """ The module with the logic of the solution of the quadratic equation """ end
For the task, we need 1 public and several private functions. The public function will contain the logic for solving the equation, and the private functions will display the original quadratic equation and the variants of the solutions obtained.
Perhaps let's start with writing tests. Let's just define the answer options of our public method. Tests will be placed in a special file generated for the top-level module.
# test/quadratic_equation_test.exs defmodule QuadraticEquationTest do use ExUnit.Case doctest QuadraticEquation end
From the school course, we remember that the quadratic equation has two, sometimes identical, roots, or no solution at all.
# test/quadratic_equation_test.exs defmodule QuadraticEquationTest do use ExUnit.Case doctest QuadraticEquation test "when discriminant less than zero" do assert QuadraticEquation.calculation(1, 2, 3) == {:fail, [error: "Discriminant less than zero!"]} end test "when discriminant equal zero" do assert QuadraticEquation.calculation(2, 4, 2) == {:success, [x1: -1.0, x2: -1.0, d: 0.0]} end test "when discriminant more than zero" do assert QuadraticEquation.calculation(2, 3, 1) == {:success, [x1: -0.5, x2: -1.0, d: 1.0]} end end
We will not run the tests right now, to begin with, we define the calculation function in QuadraticEquation. This function will take three numerical values, namely the variables a, b and c, which are inherent in the quadratic equation in the traditional notation.
# lib/quadratic_equation.ex ... @doc """ See the description of the module. """ def calculation(a, b, c) do end ...
Now we will run the tests and make sure that they have not passed.
Add a solution to the quadratic equation in our function. And also we will specify the return values of function expected by our tests.
# lib/quadratic_equation.ex ... def calculation(a, b, c) do # print_equation(a, b, c) d = :math.pow(b, 2) - 4 * a * c if d >= 0 do x1 = (-1 * b + :math.sqrt(d)) / (2 * a) x2 = (-1 * b - :math.sqrt(d)) / (2 * a) # print_success(x1, x2, d) {:success, [x1: x1, x2: x2, d: d]} else # print_fail(d) {:fail, [error: "Discriminant less than zero!"]} end end ...
Private functions are determined using the following construct ...
defp method_name do end
I will not give private methods in the article, they are in the source code of the example on GitHub.com .
Note. The @moduledoc
and @doc
necessary for the detailed description of the module essence and for the description of the function essence. Also exdoc is able to generate from them the slashed documentation, and hex.pm will generate and lay out the docks itself. In order to hide the module / public function in the generated documentation, the @moduledoc
false and / or @doc
false directive is used.
Writing a task for this sample code is not mandatory, but for the article in general, this part will be useful.
In mix applications, it is common practice to place all tasks in the lib / mix / tasks folder provided for this purpose. So first of all add this folder to your application.
$ mkdir -p lib/mix/tasks
Then create in this folder for tasks a file with the name containing the name of the main application module and the name of the task.
$ touch lib/mix/tasks/quadratic_equation.example.ex
The task will not be difficult, its responsibilities include calling the function calculation module QuadraticEquation.
# lib/mix/tasks/quadratic_equation.example.ex defmodule Mix.Tasks.QuadraticEquation.Example do use Mix.Task @shortdoc "QuadraticEquation. Example of calculation." def run(_) do QuadraticEquation.calculation(2, 3, 1) end end
The @shortdoc
annotation @shortdoc
necessary both for a brief description of the essence of your task, and for it to start to appear in the output list of the mix help
command.
$ mix help
Hex is a library of Erlang and Elixir applications.
Before publishing your mix-application to the mix.exs file, you must add a description and project metadata. Part of the metadata was generated automatically by the mix new ...
command.
# mix.exs @version "0.1.0" def project do [app: :quadratic_equation, version: @version, elixir: "~> 1.3", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, package: package, homepage_url: "https://hexdocs.pm/quadratic_equation", source_url: "https://github.com/folklore/quadratic_equation", description: "Example of creating a Mix-application - from initialization to publication.", deps: deps] end def package do [name: :quadratic_equation, files: ["lib", "mix.exs"], maintainers: ["Stanislav Gordanov"], licenses: ["MIT"], links: %{"Github" => "https://github.com/folklore/quadratic_equation"}] end
You also need a hex.pm profile for posting. If you don’t have one yet, then the easiest way to create one is to use the command ...
$ mix hex.user register
You will need to specify a username, email and password. And also to confirm the email you entered by following the link from the letter sent to you.
Before we publish the application, we need to generate documentation. In case you did not sufficiently cover your code with a description, I remind you that the modules are documented with @moduledoc
, and the functions with @doc
.
You can also add a README file to the documentation. To do this, include it in the application configuration.
# mix.exs def project do [#... docs: [extras: ["README.md"]] ] end
To generate documentation use the command ...
$ mix docs
When all the preliminary steps have been taken, you can proceed to publishing the application in the package manager. The publication itself is not intricate, and is made by the following command ...
$ mix hex.publish
Your application is now available at https://hex.pm/packages/quadratic_equation .
As you can see, generating a skeleton application using Mix is not tricky, just like publishing it to a package manager. Writing your applications on Elixir is not so difficult. Learn the language, find ideas and implement them. Forward!
» Introduction to Mix
» Organizing your Elixir project with Mix
» Create a Mix Task for an Elixir Project
» Write and publish your first Elixir library
» Writing and Publishing an Elixir Library
» Creating Elixir libraries as OTP applications
» Elixir With José Valim | Protal
» Quadratic equation
If you are interested in the functional programming language Elixir or you are simply sympathetic, then I advise you to join the Wunsh && Elixir Telegram chat.
Source: https://habr.com/ru/post/317444/
All Articles