Do we have an easy way to write functions that take specific kinds of named tuple as arguments? I mean writing a function
foo((a, b, c))
That will accept
foo((a = 42, b = 4.2, c = [2, 5]))
but not
foo((a = 4.2, b = 42, c = 25))
Typical use cases would be defining a fit function with named fit parameters (that the fitter flattens to resp. reconstructs from a flattened parameter vector).
This is kinda annoying to write:
foo((a, b, c)::NamedTuple{(:a, :b, :c), <:Tuple{Integer, Any, AbstractVector}}) = ...
I came up with this macro:
using MacroTools
macro ntargs(arguments)
@capture(arguments, (capargs__,))
argsyms = :(())
ntsyms = :(())
nttypes = :(Tuple{})
for arg in capargs
t = if arg isa Symbol
push!(argsyms.args, arg)
push!(ntsyms.args, QuoteNode(arg))
push!(nttypes.args, :Any)
:Any
else
@capture(arg, n_::t_) || error("Expected \"name::type\"")
push!(argsyms.args, n)
push!(ntsyms.args, QuoteNode(n))
push!(nttypes.args, t)
end
end
esc(:($argsyms::NamedTuple{$ntsyms,<:$nttypes}))
end
This allows you to write
foo(@ntargs a::Integer, b, c::AbstractVector) = a * b * c
foo((a = 42, b = 4.2, c = [2, 5]))
Do we already have something in this line? If not, I’ll add it to https://github.com/oschulz/ParameterShapes.jl .