I am trying to do:
d = (solver = 2, b = 3)
f = same tuple as d but without :solver
The JuliaData/NamedTuples has a delete
method, so one can do something like f = delete(d, :solver)
. It would be nice to have it for Core.NamedTuple
as well, if possible.
Current workaround:
julia> d = (solver = 2, b = 3, c = 4)
(solver = 2, b = 3, c = 4)
julia> inter = [p for p in pairs(d) if p[1] != :solver]
2-element Array{Pair{Symbol,Int64},1}:
:b => 3
:c => 4
julia> f = (; inter...)
(b = 3, c = 4)
(answered on Slack, I think by araslan)
julia> function dropnames(namedtuple::NamedTuple, names::Tuple{Vararg{Symbol}})
keepnames = Base.diff_names(Base._nt_names(namedtuple), names)
return NamedTuple{keepnames}(namedtuple)
end
dropnames (generic function with 1 method)
julia> d = (solver = 2, b = 3, c = 4)
(solver = 2, b = 3, c = 4)
julia> dropnames(d, (:solver,))
(b = 3,)
julia> dropnames(d, (:b,))
(solver = 2,)
julia> dropnames(d, (:b,:solver))
NamedTuple()
julia> dropnames(d, (:oops,))
(solver = 2, b = 3)
Very nice! Can it also become part of Base or I am being too greedy?
Base has my permission.
Is the inference failure OK (everything becomes Any
)?
I would imagine that most use-cases could get away with @generated
and val-type symbols (the symbol to drop is a source-code literal). On the other hand, I'd imagine that most uses are not performance critical.
There are some utilities for implementing this in base/namedtuple.jl. If diff_names
is used to remove the requested name(s) then @JeffreySarnoff's implementation will be inferable.
dropnames
implementation improved ^^
@JeffreySarnoff Will you do a PR for this?
(I really hope that this is in the next beta :P )
I don't know what to do about this:
julia> function dropnames(namedtuple::NamedTuple, names::Tuple{Vararg{Symbol}})
keepnames = Base.diff_names(Base._nt_names(namedtuple), names)
return NamedTuple{keepnames}(namedtuple)
end
julia> code_warntype(dropnames, (NamedTuple, Tuple{Vararg{Symbol}}))
Body::Any
1 1 โ %1 = Base.diff_names::typeof(Base.diff_names) โ
โ %2 = Base._nt_names::typeof(Base._nt_names) โ
โ %3 = %2(%%namedtuple)::Any โ
โ %4 = %1(%3, %%names)::Tuple{Vararg{Symbol,N} where N} โ
2 โ %5 = Core.apply_type(Main.NamedTuple, %4)::Type{NamedTuple{_1,T} where T<:Tuple} where _1
โ %6 = %5(%%namedtuple)::Any โ
โโโ return %6 โ
That happens because NamedTuple
is too abstract (in the cal to code_warntype
).
submitted PR https://github.com/JuliaLang/julia/pull/27725
Most helpful comment
Base has my permission.