0

I am confused about atoms and how to use them.

To be honest I am reading the documentation and just not understanding atoms :(

Can someone provide some examples or something that would explain this?

Thanks

user1354934
  • 8,139
  • 15
  • 50
  • 80

4 Answers4

5

Since this question isn't that specific, I'll just give an example usage.

One popular use of atoms in Elixir is to use them as messages for pattern matching.

E.g., say you have function which does some sort of processing of a http request. The outcome of this processing is either going to be a successful process, or a failed process.

You could therefore use atoms to indicate whether or not this processing is successful. E.g.

def process(file) do
  lines = file |> split_lines

  case lines do
    nil ->
      {:error, "failed to process file"}
    lines ->
      {:ok, lines}
  end
end

Here we are saying that the method, process/1 will return a two tuple response. If the result of our processing is successful, it will return {:ok, lines}, however if it fails (e.g. returns nil) then it will return an error. This therefore allows us to pattern match on this result.

{:ok, lines} = process('text.txt')

Therefore, we can be sure that we will always have the lines returned to us and never a nil value (because it will throw an error). This becomes extremely useful when piping multiple methods together.

For more general information on atoms, checkout these links:

Elixir School

Stack overflow Question

Community
  • 1
  • 1
Harrison Lucas
  • 2,829
  • 19
  • 25
5

from http://elixir-lang.org/getting-started/basic-types.html#atoms

Atoms are constants where their name is their own value. Some other languages call these symbols

So if you are coming from a mainstream language, they are most like constants. But more similar (ish) to a global enum in use (ie, they act like an independent data type). You introduce them generally as targets to be matched against, so they name things that your code needs some concept of

true / false is a classic case

:ok, :error is something else you will see

you might want :red, :green, :blue, or :yes, :no, :maybe, or :up, :down, :left, :right if those concepts are important code wise ( like a 2d game )

greggreg
  • 11,945
  • 6
  • 37
  • 52
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
4

You may just be over thinking it. An atom is just a value. Just like true and false are just values, you now have any word you can use as a value. In fact true, false and nil are just atoms under the hood.

Instead of passing strings around your application as internal messages, you can pass atoms. And instead of using strings as keys for maps or keyword lists you can use atoms.

Atoms come with 1 very large caveat, they are never garbage collected so you should never generate atoms programmatically, from user input or otherwise, otherwise you risk overflowing the VM if too many are created.

The maximum number of atoms you can create defaults to 1,048,576. http://erlang.org/doc/efficiency_guide/advanced.html

Here's some examples: https://github.com/itsgreggreg/elixir_quick_reference#atom

greggreg
  • 11,945
  • 6
  • 37
  • 52
  • Can you explain the caveat then? Since they are never garbage collected, how do you handle a situation where you get a ton of atoms? Like if I am doing message streams and I use atom for the keys? Thanks – user1354934 Nov 16 '16 at 00:26
  • Elixir/Erlang is never going to generate atoms automatically, you would have to do it yourself. If you are taking input and converting it to atoms you are at risk of crashing your VM, that is why you never convert input to atoms. – greggreg Nov 16 '16 at 00:30
4

Atoms are:

  • immutable like everything in Elixir
  • values like :patryk or :true (because true is actually :true)
  • similar to symbols in Ruby
  • great for keys in maps, because enable nice syntax for accessing map elements
  • enables you to use Keyword Lists- list that are actually list of tuples, but with easier access
  • foundation of message communication eg. with GenServer

Atom in maps

Map without atom can be created like that:

map = %{"author" => "patNowak"}

and accessed

map["author"]
> "patNowak"

Map with atom as key can be created easier:

map = %{author: "patNowak"} # but %{:author => "patNowak"} still works

and accessed:

map.author # as well as map[:author]
> "patNowak"

Atom in Keyword List

Keyword list is actually list of tuple(s):

list = [author: "patNowak"]
list === [{:author, "patNowak"}]
> true

And can be accessed:

list[:author] # no dot notation in this case

Atom in messaging

GenServer use by default :reply or :noreply in some cases (GS's functions call and cast will wait for these particular atoms from your handle_ functions). Most of the messages you will receive (not warnings and errors) will be atoms eg. IO.puts "hi" will print hi and return :ok.

PatNowak
  • 5,721
  • 1
  • 25
  • 31