# Macro to automatically add method with default\_rng() for functions using RNGs

**URL:** https://discourse.julialang.org/t/macro-to-automatically-add-method-with-default-rng-for-functions-using-rngs/63556
**Category:** General Usage
**Tags:** macros, random
**Created:** [June 25, 2021, 2:53pm UTC](https://discourse.julialang.org/t/macro-to-automatically-add-method-with-default-rng-for-functions-using-rngs/63556 "2021-06-25T14:53:35Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![Luapulu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luapulu/32/17669_2.png) [@Luapulu](https://discourse.julialang.org/u/Luapulu)
#### Post date: [June 25, 2021, 2:53pm UTC](https://discourse.julialang.org/t/macro-to-automatically-add-method-with-default-rng-for-functions-using-rngs/63556/1 "2021-06-25T14:53:35Z")

</div>

Does anybody have a macro so I can write something like

```julia
@with_default_rng function my_func(rng::AbstractRNG, x, y, z)
    out = # do something with rng, x, y, z
    return out
end

```

and it will automatically add the method

```julia
my_func(x, y, z) = my_func(default_rng(), x, y, z)

```

because it’s super inconvenient to have to add extra methods for every function using randomness to use the `default_rng()`.

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [June 25, 2021, 3:57pm UTC](https://discourse.julialang.org/t/macro-to-automatically-add-method-with-default-rng-for-functions-using-rngs/63556/2 "2021-06-25T15:57:38Z")

</div>

Or maybe a more general macro that lets you define a single default argument in any position.  
So that

```julia
@default_arg foo(x = a, y, z) = ...

```

expands into

```julia
foo(y, z) = foo(a, y, z)
foo(x, y, z) = ...

```

```julia
macro default_arg(ex)
    (ex.head === :function || ex.head === :(=)) || throw(ArgumentError("Invalid expression"))
    call = ex.args[1]
    call1 = copy(call)
    call2 = copy(call1)
    Nargs = length(call.args)
    for i in 2:Nargs
         arg = call.args[i]
         if Meta.isexpr(arg, :kw, 2)
             call.args[i] = arg.args[1]
             deleteat!(call1.args, i)
             call2.args[i] = arg.args[2]
             break
        end
    end
    q = quote
        $ex
        $call1 = $call2
    end
    esc(q)
end

```

Yields:

```julia

julia> @macroexpand @default_arg function my_func(rng = default_rng(), x, y, z)
           out = rand(rng)*x + y/z
       end
quote
    #= REPL[33]:17 =#
    function my_func(rng, x, y, z)
        #= REPL[39]:1 =#
        #= REPL[39]:2 =#
        out = rand(rng) * x + y / z
    end
    #= REPL[33]:18 =#
    my_func(x, y, z) = my_func(default_rng(), x, y, z)
end

julia> @default_arg function my_func(rng = default_rng(), x, y, z)
           out = rand(rng)*x + y/z
       end
my_func (generic function with 2 methods)

julia> my_func(1.2, 2.3, 4.5)
1.0098752663124524

```
