Skip to content

Commit 45b2b81

Browse files
committed
add merge and structdiff for named tuples
1 parent b19f3e7 commit 45b2b81

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

base/namedtuple.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,44 @@ end
8989
namedtuple($NT, $(args...))
9090
end
9191
end
92+
93+
# a version of `in` for the older world these generated functions run in
94+
function sym_in(x, itr)
95+
for y in itr
96+
y === x && return true
97+
end
98+
return false
99+
end
100+
101+
@generated function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}
102+
names = Symbol[an...]
103+
for n in bn
104+
if !sym_in(n, an)
105+
push!(names, n)
106+
end
107+
end
108+
vals = map(names) do n
109+
if sym_in(n, bn)
110+
:(getfield(b, $(Expr(:quote, n))))
111+
else
112+
:(getfield(a, $(Expr(:quote, n))))
113+
end
114+
end
115+
names = (names...,)
116+
:(namedtuple(NamedTuple{$names}, $(vals...)))
117+
end
118+
119+
@generated function structdiff(a::NamedTuple{an},
120+
b::Union{NamedTuple{bn},Type{NamedTuple{bn}}}) where {an,bn}
121+
names = Symbol[]
122+
for n in an
123+
if !sym_in(n, bn)
124+
push!(names, n)
125+
end
126+
end
127+
vals = map(names) do n
128+
:(getfield(a, $(Expr(:quote, n))))
129+
end
130+
names = (names...,)
131+
:(namedtuple(NamedTuple{$names}, $(vals...)))
132+
end

test/namedtuple.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,13 @@
4545
@test map(+, (x=1, y=2), (x=10, y=20)) == (x=11, y=22)
4646
@test map(string, (x=1, y=2)) == (x="1", y="2")
4747
@test map(round, (x=1//3, y=Int), (x=3, y=2//3)) == (x=0.333, y=1)
48+
49+
@test merge((a=1, b=2), (a=10,)) == (a=10, b=2)
50+
@test merge((a=1, b=2), (a=10, z=20)) == (a=10, b=2, z=20)
51+
@test merge((a=1, b=2), (z=20,)) == (a=1, b=2, z=20)
52+
53+
@test Base.structdiff((a=1, b=2), (b=3,)) == (a=1,)
54+
@test Base.structdiff((a=1, b=2, z=20), (b=3,)) == (a=1, z=20)
55+
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1)) == (a=1,)
56+
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1, a=0)) == NamedTuple()
57+
@test Base.structdiff((a=1, b=2, z=20), NamedTuple{(:b,)}) == (a=1, z=20)

0 commit comments

Comments
 (0)