View Source Lens2.Lenses.MapSet (Lens 2 v0.2.1)

Lenses that work with MapSet structures.

Summary

Functions

Like Lens.all/0, but intended for use with a MapSet.

Make a lens that points at elements containing a particular key/value pair.

Make a lens that points at elements satisfying a predicate.

Functions

@spec all() :: Lens2.lens()

Like Lens.all/0, but intended for use with a MapSet.

Here's how to update the :a values in a MapSet of maps:

 iex> lens = Lens.MapSet.all |> Lens.key?(:a)
 iex> container = MapSet.new([%{a: 1}, %{a: 2}, %{a: 3}])
 iex> Deeply.update(container, lens, & &1*100)
 MapSet.new([%{a: 100}, %{a: 200}, %{a: 300}])

all also works reasonably well with put. Given the above container and lens,

 Deeply.put(container, lens, 3)

... will produce:

 MapSet.new([%{a: 3}]

Note that the multiple maps with now-identical :a values have been correctly collapsed into one. (MapSets can't have duplicates.)

As normal, get functions return lists rather than MapSets:

 Deeply.get_all(container, lens)
 > [1, 2, 3]    # *not* MapSet.new([1, 2, 3])
@spec has!(keyword(any())) :: Lens2.lens()

Make a lens that points at elements containing a particular key/value pair.

A MapSet might contain a struct or other Access-compatible container, such as a map or struct. A lens created by this maker will select all elements with a given key that matches the given value:

iex> container = MapSet.new([%{name: "bullwinkle"}, %{name: "rocky"}])
iex> Deeply.get_all(container, Lens.MapSet.has!(name: "rocky"))
[%{name: "rocky"}]

Here, I get all the names from a keyword list that are associated with the value 2:

iex> container = [ [name: "bullwinkle", val: 1],
...>               [name: "rocky",      val: 2],
...>               [name: "natasha",    val: 2]] |> MapSet.new
iex> lens = Lens.MapSet.has!(val: 2) |> Lens.key(:name)
iex> Deeply.get_all(container, lens) |> Enum.sort
["natasha", "rocky"]

As the exclamation point suggests, an error is raised if any of the elements doesn't have the given key.

Structs are not required to implement the Access callback functions. (Indeed, even if it does implement Access.fetch/2, that's not used.)

@spec is((Lens2.value() -> boolean())) :: Lens2.lens()

Make a lens that points at elements satisfying a predicate.

Here is how you might increment all the even values of a MapSet:

iex> import Integer, only: [is_even: 1]
iex> container = MapSet.new([-1, 0, 1, 2])
iex> Deeply.update(container, Lens.MapSet.is(&is_even/1), & &1+1)
MapSet.new([-1, 1, 3])  # Note that duplicate 1 has been removed.