Elixir language

List comprehensions

Filtering

animals = [ {"Liz", :dog}, {"Margot", :cat} ]

# pattern match
for {name, :cat} <- prefs, do: name
# ["Margot"]

# guard clause
for {name, pet_choice} <- animals, pet_choice == :dog, do: name
# ["Liz"]

# anonymous function in a guard clause
cat_lover? = fn(choice) -> choice == :cat end
for {name, pet_choice} <- prefs, cat_lover?.(pet_choice), do: name
# ["Margot"]

# destructuring plus filtering
pets = [
  %{name: "Fluffy", species: :cat, sleeping: true},
  %{name: "Joe", species: :dog, sleeping: false}
]
for pet <- pets,
    name = pet.name,
    sleeping = pet.sleeping do
  "Is #{name} sleeping? #{sleeping}"
end
# => ["Is Fluffy sleeping? true"]

# applying for each list
for i <- 1..2, IO.inspect(i), j <- 5..6 do
  {i, j}
end

for i <- 1..10, Integer.is_even(i), j <- 5..6 do
  {i, j}
end
# [{2, 5}, {2, 6}, {4, 5}, ...

Atomize keys - into

You can use into and do option from comprehensions to achieve this:

style = %{"color" => "#FFF", "display" => "flex", "border" => "2px"}
for {key, val} <- style, into: %{}, do: {String.to_atom(key), val}
# %{border: "2px", color: "#FFF", display: "flex"}

Cartesian product

names = ~w[John Jane]
surnames = ~w[Doe Silva]

for name <- names,
    surname <- surnames do
  "#{name} #{surname}"
end

Unique

for n <- [1, 1, 2, 2, 2, 3], uniq: true do
  n
end

Reduce

pets = [
  %{name: "Fluffy", species: :cat, sleeping: true},
  %{name: "Joe", species: :dog, sleeping: false},
  %{name: "Joe", species: :cat, sleeping: false}
]

for pet <- pets, reduce: %{} do
  acc ->
    Map.update(acc, pet.name, [pet], &[pet|&1])
end

# Groups by name, returns a new map
%{
  "Fluffy" => [%{name: "Fluffy", sleeping: true, species: :cat}],
  "Joe" => [
    %{name: "Joe", sleeping: false, species: :cat},
    %{name: "Joe", sleeping: false, species: :dog}
  ]
}

Filter, map at same time

for %{sleeping: false} = pet <- pets, into: %{} do
  {pet.name, pet}
end

# returns
%{"Joe" => %{name: "Joe", sleeping: false, species: :cat}}