Lens (focus v0.4.0)

Lenses combine getters and setters for keys in data structures.

Lenses should match/operate over a single value in a data structure, e.g. a key in a map/struct.

Link to this section Summary

Functions

Define a struct and derive lenses for the struct's keys as functions in the module.

A lens that focuses on an index in a list.

Define a lens to Focus on a part of a data structure.

Automatically generate the valid lenses for the supplied map-like data structure.

Get a piece of a data structure that a lens Focuses on; returns {:ok, data} | {:error, :bad_lens_path} | {:error, :bad_data_structure}

Link to this section Types

Specs

t() :: %Lens{get: (any() -> any()), put: ((any() -> any()) -> any())}

Link to this section Functions

Link to this macro

deflenses(fields)

(macro)

Define a struct and derive lenses for the struct's keys as functions in the module.

Examples assume the following module:

  defmodule PersonExample do
    import Lens
    deflenses name: nil, age: nil
  end

Example

iex> function_exported?(PersonExample, :age_lens, 0)
true
iex> function_exported?(PersonExample, :name_lens, 0)
true
iex> bart = %PersonExample{name: "Bart", age: 10}
iex> PersonExample.name_lens |> Focus.view(bart)
"Bart"

end

Specs

idx(number()) :: t()

A lens that focuses on an index in a list.

Examples

iex> first_elem = Lens.idx(0)
iex> first_elem |> Focus.view([1,2,3,4,5])
1

iex> bad_index = Lens.idx(10)
iex> bad_index |> Focus.view([1,2,3])
nil
Link to this function

make_lens(path)

Specs

make_lens(any()) :: t()

Define a lens to Focus on a part of a data structure.

Examples

iex> person = %{name: "Homer"}
iex> name_lens = Lens.make_lens(:name)
iex> name_lens |> Focus.view(person)
"Homer"
iex> name_lens |> Focus.set(person, "Bart")
%{name: "Bart"}
Link to this function

make_lenses(structure)

Specs

make_lenses(Focus.Types.traversable()) :: %{
  optional(atom()) => t(),
  optional(String.t()) => t()
}

Automatically generate the valid lenses for the supplied map-like data structure.

Examples

iex> lisa = %{name: "Lisa", pets: %{cat: "Snowball"}}
iex> lisa_lenses = Lens.make_lenses(lisa)
iex> lisa_lenses.name
...> |> Focus.view(lisa)
"Lisa"
iex> pet_lenses = Lens.make_lenses(lisa.pets)
iex> lisa_lenses.pets
...> ~> pet_lenses.cat
...> |> Focus.set(lisa, "Snowball II")
%{name: "Lisa", pets: %{cat: "Snowball II"}}
Link to this function

safe_view(lens, structure)

Specs

safe_view(t(), Focus.Types.traversable()) ::
  {:error, {:lens, :bad_path}}
  | {:error, {:lens, :bad_data_structure}}
  | {:ok, any()}

Get a piece of a data structure that a lens Focuses on; returns {:ok, data} | {:error, :bad_lens_path} | {:error, :bad_data_structure}

Examples

iex> marge = %{name: "Marge", address: %{street: "123 Fake St.", city: "Springfield"}}
iex> name_lens = Lens.make_lens(:name)
iex> Lens.safe_view(name_lens, marge)
{:ok, "Marge"}