Atoms
As constantes do elixir
Atoms são constantes onde seu valor é o próprio nome. Sua definição vem com um prefixo de dois pontos :
seguido de um nome. Exemplo :apple
.
Um ato é igual a outro atom com mesmo nome.
defmodule AtomTest do
use ExUnit.Case
test "simple tests about atom" do
apple = :apple
assert apple == :apple
assert :new_atom == :new_atom
end
end
Rodando esse código teremos um relatório de sucesso.
mix test
....
Finished in 0.02 seconds (0.00s async, 0.02s sync)
1 tests, 0 failures
Atoms podem ser definidos dinamicamente, para isso poder fazer de duas formas:
Utilizando interpolação
Utilizando conversão
1. Interpolação
defmodule AtomTest do
use ExUnit.Case
# ...
test "interpolation" do
value = "noise"
new_atom = :"#{noise}"
assert new_atom == :noise
end
end
mix test
.....
Finished in 0.02 seconds (0.00s async, 0.02s sync)
2 tests, 0 failures
2. Conversão
defmodule AtomTest do
use ExUnit.Case
# ...
test "conversion" do
value = "noise"
new_atom = String.to_atom(value)
assert new_atom == :noise
end
end
mix test
......
Finished in 0.02 seconds (0.00s async, 0.02s sync)
3 tests, 0 failures
Atenção
Devemos tomar cuidado na criação de atoms dinamicamente em nossas aplicações. Quando atoms são criados eles se mantem na memória até que a aplicação reinicie. Isso quer dizer que, se tivermos uma forma de criar atoms dinamicamente exposta para o usuário, corremos o risco de usuários mal intencionados criarem N atoms, até que nossa aplicação não responda corretamente.
Temos algumas formas de evitar esse tipo de problema. Uma forma é a utilização do String.to_existing_atom/1
onde, um atom so será gerado, caso já tenha sido criado antes. Com isso podemos limitar o que pode e o que não pode ser criado.
defmodule AtomTest do
use ExUnit.Case
test "to_existing_atom/1" do
value = "atom_that_does_not_exist"
new_atom = String.to_existing_atom(value)
assert new_atom == :atom_that_does_not_exist
end
end
mix test
1) test to_existing_atom/1 (AtomTest)
test/atom_test.exs:25
** (ArgumentError) errors were found at the given arguments:
* 1st argument: not an already existing atom
code: new_atom = String.to_existing_atom("atom_that_does_not_exist")
stacktrace:
:erlang.binary_to_existing_atom("atom_that_does_not_exist", :utf8)
test/atom_test.exs:27: (test)
E caso ele já tenha sido criado, não teremos problemas
defmodule AtomTest do
use ExUnit.Case
# ...
test "atom that does exist" do
_atom = :atom_that_does_exist
value = "atom_that_does_exist"
new_atom = String.to_existing_atom(value)
assert new_atom == :atom_that_does_exist
end
end
mix test
........
Finished in 0.02 seconds (0.00s async, 0.02s sync)
5 tests, 0 failures
Conclusão
Atoms são muito utilizados no mundo elixir, são práticos e fáceis de usar. Vimos que precisamos tomar cuidado com a geração dinâmica e que podemos controlar o que pode ser criado. Mais a frente utilizaremos cada vez mais atoms para simplificar nosso código e estrutura-lo.
Last updated
Was this helpful?