View Source Pathex.Lenses (Pathex v2.2.0)

Module with collection of prebuilt paths

Link to this section Summary

Functions

Path function which works with all possible keys it can find It takes all keys and than applies inner function (or concated path) If any application fails, this lens returns :error

Path function which works with any possible key it can find It takes any key and than applies inner function (or concated path)

This macro creates path-closure successes only when predicate returns truthy value. predicate is a function which takes a structures upon which the path is called and returns a boolean (or any other type which will be treated as boolean).

This macro creates path-closure which successes only when input matches the pattern. The pattern can be just a pattern or a pattern with when. You can write this patterns just like you'd write them in case

Path function which applies inner function (or concated path-closure) to the first value it can apply it to

Path function which applies inner function (or concated path-closure) to every value it can apply it to

Link to this section Functions

@spec all() :: Pathex.t()

Path function which works with all possible keys it can find It takes all keys and than applies inner function (or concated path) If any application fails, this lens returns :error

Example:

iex> require Pathex; import Pathex
iex> alll = Pathex.Lenses.all()
iex> Pathex.over!([%{x: 0}, [x: 1]], alll ~> path(:x), fn x -> x + 1 end)
[%{x: 1}, [x: 2]]
iex> Pathex.view!(%{x: 1, y: 2, z: 3}, alll) |> Enum.sort()
[1, 2, 3]
iex> Pathex.set([x: 1, y: 0], alll, 2)
{:ok, [x: 2, y: 2]}
@spec any() :: Pathex.t()

Path function which works with any possible key it can find It takes any key and than applies inner function (or concated path)

Example:

iex> require Pathex
iex> anyl = Pathex.Lenses.any()
iex> {:ok, 1} = Pathex.view %{x: 1}, anyl
iex> {:ok, [9]} = Pathex.set  [8], anyl, 9
iex> {:ok, [x: 1, y: 2]} = Pathex.force_set [x: 0, y: 2], anyl, 1

Note that force setting value to empty map has undefined behaviour and therefore returns an error:

iex> require Pathex
iex> anyl = Pathex.Lenses.any()
iex> :error = Pathex.force_set(%{}, anyl, :well)

And note that this lens has keywords at head of list at a higher priority than non-keyword heads:

iex> require Pathex
iex> anyl = Pathex.Lenses.any()
iex> {:ok, [{:x, 1}, 2]} = Pathex.set([{:x, 0}, 2], anyl, 1)
iex> {:ok, [1, {:x, 2}]} = Pathex.set([0, {:x, 2}], anyl, 1)
iex> {:ok, [1, 2]} = Pathex.set([{"some_tuple", "here"}, 2], anyl, 1)
@spec filtering((any() -> boolean())) :: Pathex.t(any(), any())

This macro creates path-closure successes only when predicate returns truthy value. predicate is a function which takes a structures upon which the path is called and returns a boolean (or any other type which will be treated as boolean).

This function is useful when composed with star/0 and some/0

Note:
In terms of functional programming, such conditional lenses are called prisms

Example:

iex> import Pathex.Lenses; import Pathex
iex> adminl = filtering(& &1.role == :admin)
iex> {:ok, %{name: "Name", role: :admin}} = Pathex.view(%{name: "Name", role: :admin}, adminl)
iex> :error = Pathex.view(%{role: :user}, adminl)

iex> import Pathex.Lenses; import Pathex
iex> dots2d = [{1, 1}, {1, 5}, {3, 0}, {4, 3}]
iex> higher_than_2 = filtering(fn {_x, y} -> y > 2 end)
iex> {:ok, [{1, 5}, {4, 3}]} = Pathex.view(dots2d, star() ~> higher_than_2)
Link to this macro

matching(pattern)

View Source (macro)

This macro creates path-closure which successes only when input matches the pattern. The pattern can be just a pattern or a pattern with when. You can write this patterns just like you'd write them in case

This function is useful when composed with star/0 and some/0

Note:
In terms of functional programming, such conditional lenses are called prisms

Example:

iex> import Pathex.Lenses; import Pathex
iex> adminl = matching(%{role: :admin})
iex> {:ok, %{name: "Name", role: :admin}} = Pathex.view(%{name: "Name", role: :admin}, adminl)
iex> :error = Pathex.view(%{}, adminl)

iex> import Pathex.Lenses; import Pathex
iex> dots2d = [{1, 1}, {1, 5}, {3, 0}, {4, 3}]
iex> higher_than_2 = matching({_x, y} when y > 2)
iex> {:ok, [{1, 5}, {4, 3}]} = Pathex.view(dots2d, star() ~> higher_than_2)
@spec some() :: Pathex.t()

Path function which applies inner function (or concated path-closure) to the first value it can apply it to

Example:

iex> require Pathex; import Pathex
iex> somel = Pathex.Lenses.some()
iex> Pathex.view!([x: [11], y: [22], z: 33], somel ~> path(0))
11
iex> Pathex.set!([x: %{y: 0}, z: %{y: 0}], somel ~> path(:y, :map), 1)
[x: %{y: 1}, z: %{y: 0}]
iex> Pathex.view([x: 1, y: 2, z: 3], somel)
{:ok, 1}

Note:
Force update fails for empty structures

Think of this function as star() ~> any() but optimized to work with only first element

@spec star() :: Pathex.t()

Path function which applies inner function (or concated path-closure) to every value it can apply it to

Example:

iex> require Pathex; import Pathex
iex> starl = Pathex.Lenses.star()
iex> Pathex.view!(%{x: [1], y: [2], z: 3}, starl ~> path(0)) |> Enum.sort()
[1, 2]
iex> Pathex.set!(%{x: %{y: 0}, z: [3]}, starl ~> path(:y, :map), 1)
%{x: %{y: 1}, z: [3]}
iex> Pathex.view([x: 1, y: 2, z: 3], starl)
{:ok, [1, 2, 3]}

Note:
It returns :error when no data was found or changed

Think of this function as filter_map. It is particularly useful for filtering
and selecting needed values with custom functions or matching/1 macro

Example:

iex> require Pathex; import Pathex; require Pathex.Lenses
iex> starl = Pathex.Lenses.star()
iex> structure = [{1, 4}, {2, 8}, {3, 6}, {4, 10}]
iex> #
iex> # For example we want to select all tuples with first element greater than 2
iex> #
iex> greater_than_2 = Pathex.Lenses.matching({x, _} when x > 2)
iex> Pathex.view(structure, starl ~> greater_than_2)
{:ok, [{3, 6}, {4, 10}]}