AccessorsExtra.RecursiveOfTypeType
RecursiveOfType(out::Type, [optic=Children()]; [recurse::Type=Any])

Optic that references all values of type out located arbitrarily deep.

Recurses into values of type recurse (Any by default) using the specified inner optic. The default of Children() descends into all properties of objects, or into all elements of a collection.

___Note:___ typically, when changing the optic parameter, the recurse type should be narrowed as well.

Examples

julia> obj = ([1,2,3], (a=[4,5], b=[6], c=([7], [8,9])));

# extract all numbers from the object:
julia> getall(obj, RecursiveOfType(Number))
9-element Vector{Int64}:
 1
 2
 3
 4
 5
 6
 7
 8
 9

# extract the first element of each vector:
julia> getall(obj, @o _ |> RecursiveOfType(Vector) |> first)
(1, 4, 6, 7, 8)

# negate the first element of each vector:
julia> modify(x -> -x, obj, @o _ |> RecursiveOfType(Vector) |> first)
([-1, 2, 3], (a = [-4, 5], b = [-6], c = ([-7], [-8, 9])))
AccessorsExtra.concatFunction
concat(optics...)
o1 ++ o2 ++ o3 ++ ...

Concatenate multiple optics, producing a new optic that references all values from them.

Specifically, with a concat-optic:

  • getall is the concatenation of individual getalls
  • setall accepts a collection of values that are distributed over individual optics based on their getall counts
  • modify applies modify for each optic in turn, with the same transformation function
AccessorsExtra.maybeMethod
maybe(optic; [default=nothing])

Create an optional optic that references a value that may or may not be present in the object.

Note: support for default != nothing is experimental and only implemented for getting, not for setting.

maybe(o) behaves similar to o itself, with the following differences:

  • if the referenced value is present, set(obj, maybe(o), nothing) deletes it
  • if the value is absent:
    • accessing maybe(o)(obj) returns default
    • modify doesn't do anything
    • set inserts the new value

Whether the referenced value is present or not, is determined by hasoptic(obj, o).

@maybe is the macro form available for convenience: @maybe ... is equivalent to maybe(@o ...).

Examples

julia> o = maybe(@o _.a)

julia> o((a=1, b=2))
1
julia> o((b=2,))
# nothing

julia> set((a=1, b=2), o, 10)
(a = 10, b = 2)
julia> set((b=2,), o, 10)
(b = 2, a = 10)

julia> modify(x -> x+10, (a=1, b=2), o)
(a = 11, b = 2)
julia> modify(x -> x+10, (b=2,), o)
(b = 2,)

julia> modify(x -> x+10, ((a=1,), (a=2, b=3), (b=4,)), o ∘ Elements())
((a = 11,), (a = 12, b = 3), (b = 4,))