-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on #16580, also much work done by quinnj. `(a=1, ...)` syntax is implemented, and `(; ...)` syntax is implemented but not yet enabled.
- Loading branch information
1 parent
80a2c2f
commit 0cc9274
Showing
20 changed files
with
568 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
function NamedTuple{names,T}(args::Tuple) where {names, T <: Tuple} | ||
if length(args) == length(names) | ||
if @generated | ||
N = length(names) | ||
types = T.parameters | ||
Expr(:new, :(NamedTuple{names,T}), Any[ :(convert($(types[i]), args[$i])) for i in 1:N ]...) | ||
else | ||
N = length(names) | ||
NT = NamedTuple{names,T} | ||
ccall(:jl_new_structv, Any, (Any, Ptr{Void}, UInt32), NT, collect(Any, T(args)), N)::NT | ||
end | ||
else | ||
throw(ArgumentError("wrong number of arguments to named tuple constructor")) | ||
end | ||
end | ||
|
||
function NamedTuple{names}(args::Tuple) where {names} | ||
NamedTuple{names,typeof(args)}(args) | ||
end | ||
|
||
NamedTuple() = NamedTuple{(),Tuple{}}(()) | ||
|
||
length(t::NamedTuple) = nfields(t) | ||
start(t::NamedTuple) = 1 | ||
done(t::NamedTuple, iter) = iter > nfields(t) | ||
next(t::NamedTuple, iter) = (getfield(t, iter), iter + 1) | ||
endof(t::NamedTuple) = nfields(t) | ||
getindex(t::NamedTuple, i::Int) = getfield(t, i) | ||
getindex(t::NamedTuple, i::Symbol) = getfield(t, i) | ||
indexed_next(t::NamedTuple, i::Int, state) = (getfield(t,i), i+1) | ||
|
||
convert(::Type{NamedTuple{names,T}}, nt::NamedTuple{names,T}) where {names,T} = nt | ||
convert(::Type{NamedTuple{names}}, nt::NamedTuple{names}) where {names} = nt | ||
|
||
function convert(::Type{NamedTuple{names,T}}, nt::NamedTuple{names}) where {names,T} | ||
NamedTuple{names,T}(T(nt)) | ||
end | ||
|
||
function show(io::IO, t::NamedTuple) | ||
n = nfields(t) | ||
if n == 0 | ||
print(io, "NamedTuple()") | ||
else | ||
print(io, "(") | ||
for i = 1:n | ||
print(io, fieldname(typeof(t),i), " = "); show(io, getfield(t,i)) | ||
if n == 1 | ||
print(io, ",") | ||
elseif i < n | ||
print(io, ", ") | ||
end | ||
end | ||
print(io, ")") | ||
end | ||
end | ||
|
||
eltype(::Type{NamedTuple{names,T}}) where {names,T} = eltype(T) | ||
|
||
==(a::NamedTuple{n}, b::NamedTuple{n}) where {n} = Tuple(a) == Tuple(b) | ||
==(a::NamedTuple, b::NamedTuple) = false | ||
|
||
isequal(a::NamedTuple{n}, b::NamedTuple{n}) where {n} = isequal(Tuple(a), Tuple(b)) | ||
isequal(a::NamedTuple, b::NamedTuple) = false | ||
|
||
_nt_names(::NamedTuple{names}) where {names} = names | ||
_nt_names(::Type{T}) where {names,T<:NamedTuple{names}} = names | ||
|
||
hash(x::NamedTuple, h::UInt) = xor(object_id(_nt_names(x)), hash(Tuple(x), h)) | ||
|
||
isless(a::NamedTuple{n}, b::NamedTuple{n}) where {n} = isless(Tuple(a), Tuple(b)) | ||
# TODO: case where one argument's names are a prefix of the other's | ||
|
||
function map(f, nt::NamedTuple{names}, nts::NamedTuple{names}...) where names | ||
# this method makes sure we don't define a map(f) method | ||
NT = NamedTuple{names} | ||
if @generated | ||
N = length(names) | ||
M = length(nts) | ||
args = Expr[:(f($(Expr[:(getfield(nt, $j)), (:(getfield(nts[$i], $j)) for i = 1:M)...]...))) for j = 1:N] | ||
:( NT(($(args...),)) ) | ||
else | ||
NT(map(f, map(Tuple, (nt, nts...))...)) | ||
end | ||
end | ||
|
||
# a version of `in` for the older world these generated functions run in | ||
@pure function sym_in(x, itr) | ||
for y in itr | ||
y === x && return true | ||
end | ||
return false | ||
end | ||
|
||
@pure function merge_names(an, bn) | ||
names = Symbol[an...] | ||
for n in bn | ||
if !sym_in(n, an) | ||
push!(names, n) | ||
end | ||
end | ||
(names...,) | ||
end | ||
|
||
""" | ||
merge(a::NamedTuple, b::NamedTuple) | ||
Construct a new named tuple by merging two existing ones. | ||
The order of fields in `a` is preserved, but values are taken from matching | ||
fields in `b`. Fields present only in `b` are appended at the end. | ||
```jldoctest | ||
julia> merge((a=1, b=2, c=3), (b=4, d=5)) | ||
(a = 1, b = 4, c = 3, d = 5) | ||
``` | ||
""" | ||
function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn} | ||
if @generated | ||
names = merge_names(an, bn) | ||
vals = Any[ :(getfield($(sym_in(n, bn) ? :b : :a), $(Expr(:quote, n)))) for n in names ] | ||
:( NamedTuple{$names}(($(vals...),)) ) | ||
else | ||
names = merge_names(an, bn) | ||
NamedTuple{names}(map(n->getfield(sym_in(n, bn) ? b : a, n), names)) | ||
end | ||
end | ||
|
||
merge(a::NamedTuple{()}, b::NamedTuple) = b | ||
|
||
""" | ||
merge(a::NamedTuple, iterable) | ||
Interpret an iterable of key-value pairs as a named tuple, and perform a merge. | ||
```jldoctest | ||
julia> merge((a=1, b=2, c=3), [:b=>4, :d=>5]) | ||
(a = 1, b = 4, c = 3, d = 5) | ||
``` | ||
""" | ||
function merge(a::NamedTuple, itr) | ||
names = Symbol[] | ||
vals = Any[] | ||
for (k,v) in itr | ||
push!(names, k) | ||
push!(vals, v) | ||
end | ||
merge(a, NamedTuple{(names...)}((vals...,))) | ||
end | ||
|
||
keys(nt::NamedTuple{names}) where {names} = names | ||
values(nt::NamedTuple) = Tuple(nt) | ||
haskey(nt::NamedTuple, key::Union{Integer, Symbol}) = isdefined(nt, key) | ||
get(nt::NamedTuple, key::Union{Integer, Symbol}, default) = haskey(nt, key) ? getfield(nt, key) : default | ||
get(f::Callable, nt::NamedTuple, key::Union{Integer, Symbol}) = haskey(nt, key) ? getfield(nt, key) : f() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.