Elixir Gotchas
28 Sep 2020
.ex vs .exs
- .ex - compiled
- .exs - interpreted (don't need to be compiled for each change)
use vs import vs require vs alias
- Use - gives full control to another module and calls its __using__ macro
- Import - references a function from another module with its name only
- Require - ensures a module is compiled first (needed if they contain macros)
- Alias - creates additional names for modules (useful for lengthy module names)
Accessing Collection Elements
We can access map values with the access operator.
> user = %{name: "example", email: "example@example.com"}
> user[:name]
"example"
The access operator does not work on regular lists or tuples.
> list = ["a","b","c"]
> list[1]
** (ArgumentError) the Access calls for keywords expect the key
to be an atom, got: 1
(elixir 1.10.4) lib/access.ex:311: Access.get/3
Accessing list elements is done with Enum library functions.
> list = ["a","b","c"] > Enum.at(list, 1) "b" > Enum.fetch(list, 1) "b" > Enum.fetch!(list, 1) "b"
Enum.fetch/2 will return :error if the given index is out of bounds.
> Enum.fetch(list, 3) :error
Enum.fetch!/2 will throw an error if the given index is out of bounds.
> Enum.fetch!(list, 3)
** (Enum.OutOfBoundsError) out of bounds error
(elixir 1.10.4) lib/enum.ex:881: Enum.fetch!/2
The access operator does work on keyword lists.
> list = [name: "bob"] > list[:name] "bob"
Anonymous Functions
Anonymous function declarations begin with fn and end with end.
A common mistake is forgetting the end token.
> hello = fn x -> IO.puts "hello, #{x}" end
Anonymous functions are invoked with the dot operator.
> hello.("world")
hello, world
Module Attributes
Modules can contain something that looks like instance variables from Ruby.
These are called module attributes.
defmodule Example do
@default_config %{format: "txt", tabs: false}
@moduledoc """
Documentation for `Example`.
"""
end
They can be read but not modified at runtime.
Default Parameters
Default parameters are denoted with \\ instead of =.
def hello(str \\ "world") do
IO.puts "hello, #{str}"
end
Structs
Elixir provides a type of map with compile-time checks called a struct.
defmodule User do defstruct username: "example", email: "example@example.com" end
> user = %User{}
Although a struct looks similar to a map, we cannot access its values with the access operator.
> user[:email]
** (UndefinedFunctionError) function User.fetch/2 is undefined (User does not
implement the Access behaviour)
(http_test 0.1.0) User.fetch(%User{email: "example@example.com",
username: "default_username"}, :email)
(elixir 1.10.4) lib/access.ex:286: Access.get/3
Instead we use the dot operator.
> user.email "example@example.com"