Skip to content

Commit

Permalink
add merge and structdiff for named tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jun 4, 2017
1 parent 3c72902 commit d22ab50
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
41 changes: 41 additions & 0 deletions base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,44 @@ end
namedtuple($NT, $(args...))
end
end

# a version of `in` for the older world these generated functions run in
function sym_in(x, itr)
for y in itr
y === x && return true
end
return false
end

@generated function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}
names = Symbol[an...]
for n in bn
if !sym_in(n, an)
push!(names, n)
end
end
vals = map(names) do n
if sym_in(n, bn)
:(getfield(b, $(Expr(:quote, n))))
else
:(getfield(a, $(Expr(:quote, n))))
end
end
names = (names...,)
:(namedtuple(NamedTuple{$names}, $(vals...)))
end

@generated function structdiff(a::NamedTuple{an},
b::Union{NamedTuple{bn},Type{NamedTuple{bn}}}) where {an,bn}
names = Symbol[]
for n in an
if !sym_in(n, bn)
push!(names, n)
end
end
vals = map(names) do n
:(getfield(a, $(Expr(:quote, n))))
end
names = (names...,)
:(namedtuple(NamedTuple{$names}, $(vals...)))
end
10 changes: 10 additions & 0 deletions test/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,13 @@
@test map(+, (x=1, y=2), (x=10, y=20)) == (x=11, y=22)
@test map(string, (x=1, y=2)) == (x="1", y="2")
@test map(round, (x=1//3, y=Int), (x=3, y=2//3)) == (x=0.333, y=1)

@test merge((a=1, b=2), (a=10,)) == (a=10, b=2)
@test merge((a=1, b=2), (a=10, z=20)) == (a=10, b=2, z=20)
@test merge((a=1, b=2), (z=20,)) == (a=1, b=2, z=20)

@test Base.structdiff((a=1, b=2), (b=3,)) == (a=1,)
@test Base.structdiff((a=1, b=2, z=20), (b=3,)) == (a=1, z=20)
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1)) == (a=1,)
@test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1, a=0)) == NamedTuple()
@test Base.structdiff((a=1, b=2, z=20), NamedTuple{(:b,)}) == (a=1, z=20)

0 comments on commit d22ab50

Please sign in to comment.