[ANN] NamedTupleTools.jl

NamedTupleTools is a small package that makes doing a few things with NamedTuples a bit easier.
(Julia v1.0)

using NamedTupleTools

julia> namedtuple(:a, :b, :c)(1, 2.0, "three")
(a = 1, b = 2.0, c = "three")

    namedtuple(  name1, name2, ..  )
    namedtuple( (name1, name2, ..) )
       where the `names` are all `Symbols` or all `Strings`

Generate a NamedTuple prototype by specifying or obtaining the fieldnames.
The prototype is applied to fieldvalues, giving a completed NamedTuple.

julia> ntproto = namedtuple( :a, :b, :c )
NamedTuple{(:a, :b, :c),T} where T<:Tuple

julia> nt123 = ntproto(1, 2, 3)
(a = 1, b = 2, c = 3)

julia> ntAb3 = ntproto("A", "b", 3)
(a = "A", b = "b", c = 3)

julia> isprototype(ntproto)

julia> isprototype(nt123)

julia> delete!(nt123, :a) === (b = 2, c = 3)
julia> delete!(nt123, :a, :c) === delete!(nt123, (:a, :c)) === (b = 2,)
julia> delete!(ntproto, :b) === namedtuple(:a, :c)

julia> ntproto1 = namedtuple(:a, :b);
julia> ntproto2 = namedtuple(:b, :c);

julia> merge(ntproto1,ntproto2)
NamedTuple{(:a, :b, :c),T} where T<:Tuple

This looks pretty useful. Unfortunately, however, I was unable to add the package.

(v0.7) pkg> add NamedTupleTools
  Updating registry at `~/.julia/registries/General`
  Updating git-repo `https://github.com/JuliaRegistries/General.git`
 Resolving package versions...
ERROR: Unsatisfiable requirements detected for package NamedTupleTools [d9ec5142]:
 NamedTupleTools [d9ec5142] log:
 ├─possible versions are: [0.1.0, 0.2.0] or uninstalled
 ├─restricted to versions * by an explicit requirement, leaving only versions [0.1.0, 0.2.0]
 └─restricted by julia compatibility requirements to versions: uninstalled — no versions left

the package has 1.0 in its REQUIRE file and in turn cannot be installed on Julia 0.7.

1 Like

Is there a technical reason that a new module written for 1.0 cannot work with version 0.7 save the information in REQUIRE?

Having Julia 0.7 as a version that is basically 1.0 + deprecation warnings is a very useful tool as the 1.0 language stabilizes and modules/packages are ported.

As a Julia 0.7 user, it would be nice to see this continue if possible.

For the most part, a new module written for 1.0 will work with 0.7. However, they are not identical. I do not use 0.7 anymore, and so cannot see first hand what happens with that version when running new code I write. Whatever distinctions there may be in some subtle aspect of behavior, I do not represent that my new work is right for versions prior to 1.0. I appreciate your note, and – at least for this package, it is a single file that you could copy/paste into the REPL if you want. While that is not ideal for 0.7 users, I’d rather be forward focused.

1 Like

The latest release introduces an easier way to construct NamedTuples when the field names and the values to assign are available together as args to your function, or for direct use in the REPL.

using NamedTupleTools

namesof_values  = (:instrument, :madeby)
matching_values = ("violin", "Stradivarius")

nt = namedtuple(namesof_values, matching_values)
(instrument = "violin", madeby = "Stradivarius")
  • The names and the values may be given as a Tuple or as a Vector, independently.
  • The names may be given as Symbols or as Strings. The values can be of any type or types.

These examples convert, merge, or prototype NTs, and delete fields.

1 Like

Here is a way of doing it in vanilla Julia:

julia> (;zip(namesof_values, matching_values)...,)
(instrument = "violin", madeby = "Stradivarius")
1 Like

good to know (and news to me)
what does the leading semi-colon do, specifically? (in addition to making it work)

It is similar how you programatically pass keywords to functions

f(;kwargs...) = @show kwargs
d = Dict(:a => "foo", :b => "bar")
f(; d...)
# kwargs = Base.Iterators.Pairs(:a=>"foo",:b=>"bar")

Without ; you would just get a normal tuple.

Here is another way to do it:

julia> # Data
julia> namesof_values = (:instrument, :madeby)
(:instrument, :madeby)

julia> matching_values = ("violin", "Stradivarius")
("violin", "Stradivarius")

julia> # Another way to do it

julia> NamedTuple{namesof_values}(matching_values)
(instrument = "violin", madeby = "Stradivarius")
1 Like