# Macro to generate 2 keyword function parameters

**URL:** https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161
**Category:** General Usage
**Tags:** macros, keyword-arguments
**Created:** [April 17, 2025, 11:05am UTC](https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161 "2025-04-17T11:05:27Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)
#### Post date: [April 17, 2025, 11:05am UTC](https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161/1 "2025-04-17T11:05:27Z")

</div>

Let’s say I have this function

```julia
import Dates: DateTime
function myfun1(; ena::Int=1, offsettime::DateTime, entrytime::DateTime, dio::Int)
    return nothing
end

```

with the parameters being

```julia
:($(Expr(:parameters, :($(Expr(:kw, :(ena::Int), 1))), :(offsettime::Main.DateTime), :(entrytime::Main.DateTime), :(dio::Int))))

```

I wanted to create a macro that will automate writing `offsetime`, and `entrytime`.

When I do it one by one it works:

```julia
macro recvtime1()
    return :($(esc(:offsettime))::DateTime)
end
macro recvtime2()
    return :($(esc(:entrytime))::DateTime)
end
function myfun2(; ena=1, @recvtime1, @recvtime2, dio=2)
    return nothing
end

```

But when I do it together it complains for what I think is an automatically generated parenthesis:

```julia
macro recvtime()
    return :($(esc(:offsettime))::DateTime, $(esc(:entrytime))::DateTime)
end

```

The error:

```julia-repl
julia> function myfun3(; ena=1, @recvtime, dio=2)
           return nothing
       end
ERROR: syntax: invalid keyword argument syntax "(offsettime::Main.DateTime, entrytime::Main.DateTime)" around REPL[47]:1
Stacktrace:
 [1] top-level scope
   @ REPL[47]:1

```

Is there a way I can adapt `@recvtime` such that `myfun3` could work as is ?

`@macroexpand` indeed shows the extra parenthesis. I think if I can get them out it should work but I don’t see how.

```julia-repl
julia> @macroexpand @recvtime
:((offsettime::Main.DateTime, entrytime::Main.DateTime))

```

I know I can pass to the macro the whole keyword parameter list and just return an `Expr(:parameters, )` with adding the two keywords, but I prefer not to operate on that level.

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [April 17, 2025, 2:08pm UTC](https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161/2 "2025-04-17T14:08:16Z")

</div>

I would not expect this to be possible, since a macro returns a single `Expr`ession, but you’d need two.

Put differently, compare the ASTs of

```julia-repl
julia> using MacroTools: prewalk, rmlines # To get rid of the line number clutter

julia> ex_macro = prewalk(rmlines, :(function f(@m, c) end)); dump(ex_macro)
Expr
  head: Symbol function
  args: Array{Any}((2,))
    1: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol f
        2: Expr
          head: Symbol macrocall
          args: Array{Any}((2,))
            1: Symbol @m
            2: Nothing nothing
        3: Symbol c
    2: Expr
      head: Symbol block
      args: Array{Any}((0,))

```

and

```julia-repl
julia> ex_goal = prewalk(rmlines, :(function f(a, b, c) end)); dump(ex_goal)
Expr
  head: Symbol function
  args: Array{Any}((2,))
    1: Expr
      head: Symbol call
      args: Array{Any}((4,))
        1: Symbol f
        2: Symbol a
        3: Symbol b
        4: Symbol c
    2: Expr
      head: Symbol block
      args: Array{Any}((0,))

```

We need the macro `m` to alter `ex_macro.args[1].args`, while it can only see `ex_macro.args[1].args[2]`.

---

<div class="post-metadata">

### Author: ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)
#### Post date: [April 17, 2025, 2:20pm UTC](https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161/3 "2025-04-17T14:20:19Z")

</div>

Yeah. I had the impression this might be impossible to do. And splatting with `...` doesn’t seem to do the trick as well.

---

<div class="post-metadata">

### Author: ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)
#### Post date: [April 17, 2025, 3:43pm UTC](https://discourse.julialang.org/t/macro-to-generate-2-keyword-function-parameters/128161/4 "2025-04-17T15:43:57Z")

</div>

> I know I can pass to the macro the whole keyword parameter list and just return an `Expr(:parameters, )` with adding the two keywords, but I prefer not to operate on that level.

I ended up passing the whole function to the macro irregardless my preference:

```julia
macro recvtime(funexpr)
    parametersdad = funexpr.args[1]
    # search
    ff = findfirst(ex -> Base.isexpr(ex, :parameters), parametersdad.args)
    if isnothing(ff)
        newpars = Expr(:parameters, :($(esc(:offsettime))::DateTime), :($(esc(:entrytime))::DateTime) )
        insert!(funexpr.args[1].args, 2, newpars)
    else
        exprpar = parametersdad.args[ff]
        newpars = Expr(:parameters, exprpar.args..., :($(esc(:offsettime))::DateTime), :($(esc(:entrytime))::DateTime) )
        funexpr.args[1].args[ff] = newpars
    end
    return funexpr
end

```

Puts the two extra keyword parameters in the function

```julia
julia> @recvtime function myfun3(; ena=1, dio=2)
           return nothing
       end

```
