Skip to content

Commit e528129

Browse files
committed
more vectors support; reorder code
1 parent 53311f1 commit e528129

File tree

2 files changed

+33
-31
lines changed

2 files changed

+33
-31
lines changed

src/getsetall.jl

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ setall(obj, o::If, vs) = error("Not supported")
3838
setall(obj, o, vs) = set(obj, o, only(vs))
3939

4040

41-
# A recursive implementation of getall doesn't actually infer,
41+
# A straightforward recursive implementation of getall and setall don't actually infer,
4242
# see https://github.com/JuliaObjects/Accessors.jl/pull/64.
43-
# Instead, we need to generate unrolled code explicitly.
43+
# Instead, we need to generate separate functions for each recursion level.
44+
4445
function getall(obj, optic::ComposedFunction)
4546
N = length(decompose(optic))
4647
_getall(obj, optic, Val(N))
@@ -53,20 +54,8 @@ function setall(obj, optic::ComposedFunction, vs)
5354
end
5455

5556

57+
# _getall: the actual workhorse for getall
5658
_getall(_, _, ::Val{N}) where {N} = error("Too many chained optics: $N is not supported for now. See also https://github.com/JuliaObjects/Accessors.jl/pull/64.")
57-
_setall(_, _, _, ::Val{N}) where {N} = error("Too many chained optics: $N is not supported for now. See also https://github.com/JuliaObjects/Accessors.jl/pull/68.")
58-
59-
_concat(a::Tuple, b::Tuple) = (a..., b...)
60-
_concat(a::Tuple, b::AbstractVector) = vcat(collect(a), b)
61-
_concat(a::AbstractVector, b::Tuple) = vcat(a, collect(b))
62-
_concat(a::AbstractVector, b::AbstractVector) = vcat(a, b)
63-
_reduce_concat(xs::Tuple) = reduce(_concat, xs; init=())
64-
_reduce_concat(xs::AbstractVector) = reduce(append!, xs; init=eltype(eltype(xs))[])
65-
# fast path:
66-
_reduce_concat(xs::Tuple{AbstractVector, Vararg{AbstractVector}}) = reduce(vcat, xs)
67-
_reduce_concat(xs::AbstractVector{<:AbstractVector}) = reduce(vcat, xs)
68-
69-
7059
_getall(obj, optic, ::Val{1}) = getall(obj, optic)
7160
for i in 2:10
7261
@eval function _getall(obj, optic, ::Val{$i})
@@ -78,20 +67,41 @@ for i in 2:10
7867
end
7968
end
8069

70+
# _setall: the actual workhorse for setall
71+
# takes values as a nested tuple with proper leaf lengths, prepared in setall above
72+
_setall(_, _, _, ::Val{N}) where {N} = error("Too many chained optics: $N is not supported for now. See also https://github.com/JuliaObjects/Accessors.jl/pull/68.")
73+
_setall(obj, optic, vs, ::Val{1}) = setall(obj, optic, vs)
74+
for i in 2:10
75+
@eval function _setall(obj, optic, vs, ::Val{$i})
76+
setall(obj, optic.inner, map(getall(obj, optic.inner), vs) do obj, vss
77+
_setall(obj, optic.outer, vss, Val($(i - 1)))
78+
end)
79+
end
80+
end
81+
82+
83+
_concat(a::Tuple, b::Tuple) = (a..., b...)
84+
_concat(a::Tuple, b::AbstractVector) = vcat(collect(a), b)
85+
_concat(a::AbstractVector, b::Tuple) = vcat(a, collect(b))
86+
_concat(a::AbstractVector, b::AbstractVector) = vcat(a, b)
87+
_reduce_concat(xs::Tuple) = reduce(_concat, xs; init=())
88+
_reduce_concat(xs::AbstractVector) = reduce(append!, xs; init=eltype(eltype(xs))[])
89+
# fast path:
90+
_reduce_concat(xs::Tuple{AbstractVector, Vararg{AbstractVector}}) = reduce(vcat, xs)
91+
_reduce_concat(xs::AbstractVector{<:AbstractVector}) = reduce(vcat, xs)
8192

82-
_staticlength(::Number) = Val(1)
8393
_staticlength(::NTuple{N, <:Any}) where {N} = Val(N)
8494
_staticlength(x::AbstractVector) = length(x)
8595

8696
_val(N::Int) = N
8797
_val(::Val{N}) where {N} = N
88-
_val(::Type{Val{N}}) where {N} = N
8998

9099

91100
getall_lengths(obj, optic, ::Val{1}) = _staticlength(getall(obj, optic))
92101
for i in 2:10
93102
@eval function getall_lengths(obj, optic, ::Val{$i})
94-
map(getall(obj, optic.inner)) do o
103+
# convert to Tuple: vectors cannot be put into Val
104+
map(getall(obj, optic.inner) |> Tuple) do o
95105
getall_lengths(o, optic.outer, Val($(i - 1)))
96106
end
97107
end
@@ -119,14 +129,3 @@ for i in 2:10
119129
:( ($(subs...),) )
120130
end
121131
end
122-
123-
124-
_setall(obj, optic, vs, ::Val{1}) = setall(obj, optic, vs)
125-
for i in 2:10
126-
@eval function _setall(obj, optic, vs, ::Val{$i})
127-
setall(obj, optic.inner, map(getall(obj, optic.inner), vs) do obj, vss
128-
_setall(obj, optic.outer, vss, Val($(i - 1)))
129-
end)
130-
end
131-
end
132-

test/test_getsetall.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ end
8585
@test (a=1, b=((c=-3., d=-4.), (c=-5., d=-6.))) === @inferred setall(obj, @optic(_.b |> Elements() |> Properties() |> _ * 3), [-9, -12, -15, -18])
8686

8787
obj = ([1, 2], 3:5, (6,))
88-
@test [1, 2, 3, 4, 5, 6] == @inferred getall(obj, @optic _ |> Elements() |> Elements())
89-
@test [2, 3, 4, 5, 6, 7] == @inferred getall(obj, @optic _ |> Elements() |> Elements() |> _ + 1)
88+
@test obj == setall(obj, @optic(_ |> Elements() |> Elements()), 1:6)
89+
@test ([2, 3], 4:6, (7,)) == setall(obj, @optic(_ |> Elements() |> Elements() |> _ - 1), 1:6)
90+
# can this infer?..
91+
@test_broken obj == @inferred setall(obj, @optic(_ |> Elements() |> Elements()), 1:6)
92+
@test_broken ([2, 3], 4:6, (7,)) == @inferred setall(obj, @optic(_ |> Elements() |> Elements() |> _ - 1), 1:6)
9093
end
9194

9295
end

0 commit comments

Comments
 (0)