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

Lenses specific to lists, plus one that works on both lists and tuples.

Deeply.put/3 and Deeply.update/3 produce lists when applied to lists, tuples when applied to tuples. As always, Deeply.get_all/2 produces a list whether it operates on a list or a tuple.

These lenses do not work on Enumerables (except for lists).

Summary

Functions

Returns a lens that points to the n-th element of a list or tuple.

Returns a lens that points after the last element of a list.

Returns a lens that points before the given index, but after the prevous element.

Returns a lens that points after the given index, but before the next element.

Returns a lens that points before the first element of a list.

An alias for at.

Returns a lens that points to all of the supplied indices.

Functions

@spec at(non_neg_integer()) :: Lens2.lens()

Returns a lens that points to the n-th element of a list or tuple.

iex>  lens = Lens.at(1)
iex>  Deeply.get_only({00, 10, 20}, lens)
10
iex>  Deeply.update([00, 10, 20], lens, & &1 / 10)
[00, 1.0, 20]
iex>  Deeply.put({"my", "whiny", "tuple"}, lens, "favorite")
{"my", "favorite", "tuple"}

Indexes that are out of bounds are not allowed for tuples:

iex>  tuple = {1, 2, 3}
iex>  assert_raise(ArgumentError, fn ->
...>    Deeply.get_all(tuple, Lens.at(-1))
...>  end)
iex>  assert_raise(ArgumentError, fn ->
...>    Deeply.get_all(tuple, Lens.at(3))
...>  end)

Negative indices are allowed for lists and have their usual meaning (count backwards):

iex> Deeply.put([0, 1, 2], Lens.at(-1), :NEW)
[0, 1, :NEW]

Indexes beyond the end of the list are ignored. (This behavior is consistent with List.update_at/3 and List.replace_at/3.)

iex> Deeply.put([0, 1, 2], Lens.at(3), :NEW)
[0, 1, 2]
@spec back() :: Lens2.lens()

Returns a lens that points after the last element of a list.

Since there is nothing there, Deeply.get_only/2 returns nil:

 iex> Deeply.get_only([0, 1, 2], Lens.back)
 nil

However, you can use it to append to the list:

 iex> Deeply.put([0, 1, 2], Lens.back, :NEW)
 [0, 1, 2, :NEW]

Raises an error if used on a tuple.

@spec before(non_neg_integer()) :: Lens2.lens()

Returns a lens that points before the given index, but after the prevous element.

Since there is nothing there, Deeply.get_only/2 returns nil:

 iex> Deeply.get_only([0, 1, 2], Lens.before(2))
 nil

However, you can use it to insert into the list:

 iex> Deeply.put([0, 1, 2], Lens.before(2), :NEW)
 [0, 1, :NEW, 2]

Raises an error if used on a tuple.

@spec behind(non_neg_integer()) :: Lens2.lens()

Returns a lens that points after the given index, but before the next element.

Since there is nothing there, Deeply.get_only/2 returns nil:

 iex> Deeply.get_only([0, 1, 2], Lens.behind(0))
 nil

However, you can use it to insert into the list:

 iex> Deeply.put([0, 1, 2], Lens.behind(0), :NEW)
 [0, :NEW, 1, 2]

Raises an error if used on a tuple.

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

Returns a lens that points before the first element of a list.

Since there is nothing there, Deeply.get_only/2 returns nil:

 iex> Deeply.get_only([0, 1, 2], Lens.front)
 nil

However, you can use it to prepend to the list:

 iex> Deeply.put([0, 1, 2], Lens.front, :NEW)
 [:NEW, 0, 1, 2]

front raises an error if used on a tuple.

@spec index(non_neg_integer()) :: Lens2.lens()

An alias for at.

@spec indices([non_neg_integer()]) :: Lens2.lens()

Returns a lens that points to all of the supplied indices.

 iex> lens = Lens.indices([0, 2])
 iex> Deeply.get_all([00, 10, 20, 30], lens)
 [00, 20]
 iex> Deeply.put([00, 10, 20, 30], lens, :NEW)
 [:NEW, 10, :NEW, 30]

Alas, you cannot use a range to refer to an Enum.slice/2 of indices.

The handling of out-of-bounds elements is consistent with at/1. Negative indices count from the end, and out-of-range indices are ignored.

 iex> lens = Lens.indices([0, 2, -1, 40])
 iex> Deeply.get_all([00, 10, 20, 30], lens)
 [00, 20, 30, nil]
 iex> Deeply.put([00, 10, 20, 30], lens, :NEW)
 [:NEW, 10, :NEW, :NEW]

Raises an error if used on a tuple.