# Easy way to define functions with specific NamedTuple arguments?

**URL:** <https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483>\
**Category:** General Usage\
**Created:** [November 13, 2018, 4:43pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483 "2018-11-13T16:43:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [November 13, 2018, 4:43pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/1 "2018-11-13T16:43:23Z")

</div>

Do we have an easy way to write functions that take specific kinds of named tuple as arguments? I mean writing a function

```julia
foo((a, b, c))

```

That will accept

```julia
foo((a = 42, b = 4.2, c = [2, 5]))

```

but not

```julia
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:

```julia
foo((a, b, c)::NamedTuple{(:a, :b, :c), <:Tuple{Integer, Any, AbstractVector}}) = ...

```

I came up with this macro:

```julia
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

```julia
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](https://github.com/oschulz/ParameterShapes.jl) .

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [November 13, 2018, 5:14pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/2 "2018-11-13T17:14:53Z")

</div>

For this specific case, something like:

```julia
julia> foo(a::NamedTuple) = _foo(;a...);

julia> _foo(; a::Integer, b::Any, c::AbstractVector) = "stuff";

julia> foo((a = 42, b = 4.2, c = [2, 5]))
"stuff"

julia> foo((a = 4.2, b = 42, c = 25))
ERROR: TypeError: in #_foo, in typeassert, expected Integer, got Float64

```

could work.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 13, 2018, 5:31pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/3 "2018-11-13T17:31:37Z")

</div>

I have a small package

[https://github.com/tpapp/EponymTuples.jl/](https://github.com/tpapp/EponymTuples.jl/)

which allows you to use

```julia
f(@eponymargs(a::Integer, b, c::AbstractVector)) = ...

```

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [November 13, 2018, 7:31pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/4 "2018-11-13T19:31:05Z")

</div>

Hah, I should have known you had something for that, Tamas. 🙂

Very nice, thanks! This can up while I was developing ParameterShapes.jl (not registered yet), I hope that will somewhat complement your TransformVariables.jl, that’s why I was looking for such function defs.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 13, 2018, 7:52pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/5 "2018-11-13T19:52:11Z")

</div>

It should work fine with TransformVariables syntax for `NamedTuple`s, ie

```julia
as((a = ..., b = ..., c = ...))

```

(after all, it is just a macro expanding to valid syntax). Using it to program complex Bayesian models was my motivation for writing it.

The only issue you may run into is

[https://github.com/JuliaDocs/DocStringExtensions.jl/issues/67](https://github.com/JuliaDocs/DocStringExtensions.jl/issues/67)

which is orthogonal to both packages and is a consequence of how destructuring works at the moment.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [November 13, 2018, 8:10pm UTC](https://discourse.julialang.org/t/easy-way-to-define-functions-with-specific-namedtuple-arguments/17483/6 "2018-11-13T20:10:58Z")

</div>

Yes, Bayesian analysis was exactly my use case (for [GitHub - bat/BAT.jl: A Bayesian Analysis Toolkit in Julia](https://github.com/bat/BAT.jl)). 🙂

We’re planning to use your HMC sampler in BAT.jl too (in addition to Metropolis-Hastings).
