Skip to content

Commit a6ef462

Browse files
committed
Reconstruct with all fieldnames
This ensures that important, non-fmappable properties with non-default values are preserved.
1 parent fa1a212 commit a6ef462

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

src/functor.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ functor(::Type{<:AbstractArray}, x) = x, y -> y
88
functor(::Type{<:AbstractArray{<:Number}}, x) = (), _ -> x
99

1010
function makefunctor(m::Module, T, fs = fieldnames(T))
11+
yᵢ = 0
12+
escargs = map(fieldnames(T)) do f
13+
f in fs ? :(y[$(yᵢ += 1)]) : :(x.$f)
14+
end
15+
escfs = [:($f=x.$f) for f in fs]
16+
1117
@eval m begin
12-
$Functors.functor(::Type{<:$T}, x) = ($([:($f=x.$f) for f in fs]...),), y -> $T(y...)
18+
$Functors.functor(::Type{<:$T}, x) = ($(escfs...),), y -> $T($(escargs...))
1319
end
1420
end
1521

test/basics.jl

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
11
using Functors, Test
22

3-
struct Foo
4-
x
5-
y
6-
end
3+
@testset "Nested" begin
4+
struct Foo
5+
x
6+
y
7+
end
78

8-
@functor Foo
9+
@functor Foo
910

10-
struct Bar
11-
x
12-
end
11+
struct Bar
12+
x
13+
end
1314

14-
@functor Bar
15+
@functor Bar
1516

16-
model = Bar(Foo(1, [1, 2, 3]))
17+
model = Bar(Foo(1, [1, 2, 3]))
1718

18-
model′ = fmap(float, model)
19+
model′ = fmap(float, model)
1920

20-
@test model.x.y == model′.x.y
21-
@test model′.x.y isa Vector{Float64}
21+
@test model.x.y == model′.x.y
22+
@test model′.x.y isa Vector{Float64}
23+
end
24+
25+
@testset "Property list" begin
26+
struct Baz
27+
x
28+
y
29+
z
30+
end
31+
32+
@functor Baz (y,)
33+
34+
model = Baz(1, 2, 3)
35+
model′ = fmap(x -> 2x, model)
36+
37+
@test (model′.x, model′.y, model′.z) == (1, 4, 3)
38+
end

0 commit comments

Comments
 (0)