Skip to content

Commit

Permalink
add shortcuts for Elements(), Properties(), @optic (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
aplavin authored Jan 6, 2024
1 parent 2b0c6c2 commit d5bf87b
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/optics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ end
Elements
Access all elements of a collection that implements `map`.
An alias for `Elements()` is available as `∗` (`\\ast`). This optic can also be written as `@optic _[∗]`.
```jldoctest
julia> using Accessors
Expand Down Expand Up @@ -296,7 +297,8 @@ end
"""
Properties()
Access all properties of an objects.
Access all properties of an object.
An alias for `Properties()` is available as `∗ₚ` (`\\ast\\_p`). This optic can also be written as `@optic _[∗ₚ]`.
```jldoctest
julia> using Accessors
Expand Down
25 changes: 20 additions & 5 deletions src/sugar.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export @set, @optic, @reset, @modify, @delete, @insert, @accessor
export @set, @optic, @o, @reset, @modify, @delete, @insert, @accessor, ,
using MacroTools

"""
Expand Down Expand Up @@ -453,11 +453,24 @@ macro accessor(ex)
end |> esc
end

### shortcuts:
# optic macro
const var"@o" = var"@optic"

# Elements, Properties
const = Elements()
const = Properties()
IndexLens(::Tuple{Elements}) = Elements()
IndexLens(::Tuple{Properties}) = Properties()

### nice show() for optics
_shortstring(prev, o::PropertyLens{field}) where {field} = "$prev.$field"
_shortstring(prev, o::IndexLens) ="$prev[$(join(repr.(o.indices), ", "))]"
_shortstring(prev, o::Function) = "$o($prev)"
_shortstring(prev, o::Base.Fix1) = "$(o.f)($(o.x), $prev)"
_shortstring(prev, o::Base.Fix2) = "$(o.f)($prev, $(o.x))"
_shortstring(prev, o::Elements) = "$prev[∗]"
_shortstring(prev, o::Properties) = "$prev[∗ₚ]"

function show_optic(io, optic)
opts = deopcompose(optic)
Expand All @@ -475,13 +488,15 @@ function show_optic(io, optic)
end
end

Base.show(io::IO, optic::Union{IndexLens, PropertyLens}) = show_optic(io, optic)
Base.show(io::IO, ::MIME"text/plain", optic::Union{IndexLens, PropertyLens}) = show(io, optic)
const _OpticsTypes = Union{IndexLens,PropertyLens,Elements,Properties}

Base.show(io::IO, optic::_OpticsTypes) = show_optic(io, optic)
Base.show(io::IO, ::MIME"text/plain", optic::_OpticsTypes) = show(io, optic)

# only need show(io, optic) here because Base defines show(io::IO, ::MIME"text/plain", c::ComposedFunction) = show(io, c)
Base.show(io::IO, optic::ComposedFunction{<:Any, <:Union{IndexLens, PropertyLens}}) = show_optic(io, optic)
Base.show(io::IO, optic::ComposedFunction{<:Any, <:_OpticsTypes}) = show_optic(io, optic)
# resolve method ambiguity with Base:
Base.show(io::IO, optic::ComposedFunction{typeof(!), <:Union{IndexLens, PropertyLens}}) = show_optic(io, optic)
Base.show(io::IO, optic::ComposedFunction{typeof(!), <:_OpticsTypes}) = show_optic(io, optic)

# debugging
show_composition_order(optic) = (show_composition_order(stdout, optic); println())
Expand Down
12 changes: 12 additions & 0 deletions test/test_optics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,16 @@ end
@test Accessors.DynamicIndexLens(lastindex).([(1,2,3), (4,5)]) == [3, 5]
end

@testset "shortcuts" begin
@test (@o _.a[2]) === (@optic _.a[2])
@test (@optic _[]) === Elements()
@test (@optic _.a[][2]) === (@optic _.a |> Elements() |> _[2])
@test (@optic _.a[ₚ][2]) === (@optic _.a |> Properties() |> _[2])
# user-defined symbols have priority, same as elsewhere in Julia
let = 3
o = @optic _[]
@test o([1,2,42]) == 42
end
end

end#module

0 comments on commit d5bf87b

Please sign in to comment.