Skip to content

Commit 9291e07

Browse files
committed
Add tests for composition of head/tail and init/last
1 parent e0adba7 commit 9291e07

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

src/varname.jl

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -967,8 +967,11 @@ string_to_varname(str::AbstractString) = dict_to_varname(JSON.parse(str))
967967
968968
Get the innermost layer of an optic.
969969
970+
For all (normalised) optics, we have that `normalise(_tail(optic) ∘
971+
_head(optic) == optic)`.
972+
970973
!!! note
971-
Does not perform optic normalisation. You may wish to call
974+
Does not perform optic normalisation on the input. You may wish to call
972975
`normalise(optic)` before using this function if the optic you are passing
973976
was not obtained from a VarName.
974977
@@ -999,8 +1002,11 @@ _head(::typeof(identity)) = identity
9991002
10001003
Get everything but the innermost layer of an optic.
10011004
1005+
For all (normalised) optics, we have that `normalise(_tail(optic) ∘
1006+
_head(optic) == optic)`.
1007+
10021008
!!! note
1003-
Does not perform optic normalisation. You may wish to call
1009+
Does not perform optic normalisation on the input. You may wish to call
10041010
`normalise(optic)` before using this function if the optic you are passing
10051011
was not obtained from a VarName.
10061012
@@ -1031,8 +1037,11 @@ _tail(::typeof(identity)) = identity
10311037
10321038
Get the outermost layer of an optic.
10331039
1040+
For all (normalised) optics, we have that `normalise(_last(optic) ∘
1041+
_init(optic)) == optic`.
1042+
10341043
!!! note
1035-
Does not perform optic normalisation. You may wish to call
1044+
Does not perform optic normalisation on the input. You may wish to call
10361045
`normalise(optic)` before using this function if the optic you are passing
10371046
was not obtained from a VarName.
10381047
@@ -1063,8 +1072,11 @@ _last(::typeof(identity)) = identity
10631072
10641073
Get everything but the outermost layer of an optic.
10651074
1075+
For all (normalised) optics, we have that `normalise(_last(optic) ∘
1076+
_init(optic)) == optic`.
1077+
10661078
!!! note
1067-
Does not perform optic normalisation. You may wish to call
1079+
Does not perform optic normalisation on the input. You may wish to call
10681080
`normalise(optic)` before using this function if the optic you are passing
10691081
was not obtained from a VarName.
10701082
@@ -1084,7 +1096,9 @@ identity (generic function with 1 method)
10841096
julia> AbstractPPL._init(Accessors.@o _)
10851097
identity (generic function with 1 method)
10861098
"""
1087-
_init(o::ComposedFunction{Outer,Inner}) where {Outer,Inner} = _init(o.outer) o.inner
1099+
# This one needs normalise because it's going 'against' the direction of the
1100+
# linked list (otherwise you will end up with identities scattered throughout)
1101+
_init(o::ComposedFunction{Outer,Inner}) where {Outer,Inner} = normalise(_init(o.outer) o.inner)
10881102
_init(::Accessors.PropertyLens) = identity
10891103
_init(::Accessors.IndexLens) = identity
10901104
_init(::typeof(identity)) = identity

test/varname.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,54 @@ end
252252
@test string_to_varname(varname_to_string(vn)) == vn
253253
end
254254

255+
@testset "head, tail, init, last" begin
256+
@testset "specification" begin
257+
@test AbstractPPL._head(@o _.a.b.c) == @o _.a
258+
@test AbstractPPL._tail(@o _.a.b.c) == @o _.b.c
259+
@test AbstractPPL._init(@o _.a.b.c) == @o _.a.b
260+
@test AbstractPPL._last(@o _.a.b.c) == @o _.c
261+
262+
@test AbstractPPL._head(@o _[1][2][3]) == @o _[1]
263+
@test AbstractPPL._tail(@o _[1][2][3]) == @o _[2][3]
264+
@test AbstractPPL._init(@o _[1][2][3]) == @o _[1][2]
265+
@test AbstractPPL._last(@o _[1][2][3]) == @o _[3]
266+
267+
@test AbstractPPL._head(@o _.a) == @o _.a
268+
@test AbstractPPL._tail(@o _.a) == identity
269+
@test AbstractPPL._init(@o _.a) == identity
270+
@test AbstractPPL._last(@o _.a) == @o _.a
271+
272+
@test AbstractPPL._head(@o _[1]) == @o _[1]
273+
@test AbstractPPL._tail(@o _[1]) == identity
274+
@test AbstractPPL._init(@o _[1]) == identity
275+
@test AbstractPPL._last(@o _[1]) == @o _[1]
276+
277+
@test AbstractPPL._head(identity) == identity
278+
@test AbstractPPL._tail(identity) == identity
279+
@test AbstractPPL._init(identity) == identity
280+
@test AbstractPPL._last(identity) == identity
281+
end
282+
283+
@testset "composition" begin
284+
varnames = (
285+
@varname(x),
286+
@varname(x[1]),
287+
@varname(x.a),
288+
@varname(x.a.b),
289+
@varname(x[1].a),
290+
)
291+
for vn in varnames
292+
optic = getoptic(vn)
293+
@test AbstractPPL.normalise(
294+
AbstractPPL._last(optic) AbstractPPL._init(optic)
295+
) == optic
296+
@test AbstractPPL.normalise(
297+
AbstractPPL._tail(optic) AbstractPPL._head(optic)
298+
) == optic
299+
end
300+
end
301+
end
302+
255303
@testset "prefix and unprefix" begin
256304
@testset "basic cases" begin
257305
@test prefix(@varname(y), @varname(x)) == @varname(x.y)

0 commit comments

Comments
 (0)