# Optional macro invocation

**URL:** https://discourse.julialang.org/t/optional-macro-invocation/18588
**Category:** General Usage
**Created:** [December 12, 2018, 8:50am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588 "2018-12-12T08:50:41Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 12, 2018, 8:50am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/1 "2018-12-12T08:50:41Z")

</div>

What’s the idiomatic and DRY way of writing something like this:

```julia
function foo(async::Bool) 
  if async 
    @async dostuff()
  else 
    dostuff()
end

```

The problem here is that the code is not DRY, I have to call `dostuff()` twice (and the problem is, in general, there will be more logic duplicated).

I tried referencing the macro but it errors out (syntax error) - in the line of:

```julia
function foo(async::Bool) 
  doasync = async ? @async : @sync # errors out
  doasync dostuff()
end 

```

Any idea? It’s a pretty common pattern for me, for example, I have many instances where if a debug flag is set, certain computations are prefixed with `@time`. Now it’s the same non-DRY mess.

Thanks!

---

<div class="post-metadata">

### Author: ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)
#### Post date: [December 12, 2018, 10:23am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/2 "2018-12-12T10:23:40Z")

</div>

Does this help ?

```julia
macro maybeasync(asyncflag, expr)
    quote
        if $(esc(asyncflag))
            @async $(esc(expr))
        else
            $(esc(expr))
        end
    end
end

function docos(flag)
     @maybeasync flag cos(1)
end

```

```julia
julia> docos(true)
Task (done) @0x00007f49b7e4a4a0

julia> docos(false)
0.5403023058681398

```

EDIT: There’s probably a cheaper way to do it, in terms of code generation.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 12, 2018, 10:38am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/3 "2018-12-12T10:38:28Z")

</div>

Yes, I was leaning towards a macro myself.

If this is the only way to go, I guess it should be something at one level of abstraction higher, to pass the macro, the flag, and the expression (so that it will work with `@async` but also with `@time` and others).

And again, I guess one of the issues will be that macros can’t be passed around (referenced) as arguments (or at least I don’t know how).

---

<div class="post-metadata">

### Author: ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)
#### Post date: [December 12, 2018, 11:10am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/4 "2018-12-12T11:10:15Z")

</div>

Yeah. I thought the same thing about a more general macro. This is probably already implemented in a few utility files scattered around github…

```julia
macro maybemacro(asyncflag, themacro, expr)
    mccall = Expr(:macrocall, Symbol("@", themacro), LineNumberNode(@ __LINE__ ), expr)
    quote
        if $(esc(asyncflag))
            $mccall
        else
            $(esc(expr))
        end
    end
end

```

```julia
julia> @maybemacro true async cos(1)
Task (done) @0x00007f115df46980

julia> @maybemacro false async cos(1)
0.5403023058681398

julia> @maybemacro true time cos(1)
  0.000002 seconds (5 allocations: 176 bytes)
0.5403023058681398

julia> @maybemacro false time cos(1)
0.5403023058681398

```

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [December 12, 2018, 3:34pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/5 "2018-12-12T15:34:38Z")

</div>

This is where it’d be nice to have first-class macros like first-class functions.

---

<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: [December 12, 2018, 4:22pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/6 "2018-12-12T16:22:31Z")

</div>

> [@essenciary](#):
>
> have to call `dostuff()` twice (and the problem is, in general, there will be more logic duplicated).

While others have given nice solutions with macros, frankly I would just use a closure, possibly with some syntactic help like

```julia
doit(f, ::Val{true}) = @async f()
doit(f, ::Val{false}) = f()

doit(async_flag) do 
    # stuff goes here
end

```

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 16, 2018, 10:15am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/7 "2018-12-16T10:15:53Z")

</div>

Thanks so much, @jlapeyre and @Tamas_Papp - I’ll give the two approaches a try today, to see how they work.

They both look great although in the general case I believe that the macro approach could be more efficient as it won’t evaluate the input on every function call. Similar to [Metaprogramming · The Julia Language](https://docs.julialang.org/en/v1/manual/metaprogramming/index.html#Hold-up:-why-macros?-1)

@Mason first-class macros would be awesome. It looks like lisp-style macros could be “upgraded” to first-class macros. I’d love to see that in Julia.

---

<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: [December 16, 2018, 10:31am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/8 "2018-12-16T10:31:36Z")

</div>

> [@essenciary](#):
>
> the macro approach could be more efficient as it won’t evaluate the input on every function call.

I may be missing something, but if you branch (either via methods or an `if`) then it should be called only once.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 18, 2018, 9:59am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/9 "2018-12-18T09:59:27Z")

</div>

Sorry, I don’t think I properly articulated what was going through my head.

I have these global (environment) variables which are set upon application initialisation and don’t change throughout the lifetime of the script. Things like `DEBUG = true | false`, `ENV = dev | test | prod`, etc. These affect whether or not subsequent macros like `@time`, `@async`, etc are used (ie if `ENV == dev` then many statements are prefixed by the `@time` macro; but in `prod` they are not).

I was thinking that with macros I can remove the `IF` evaluation altogether and just use the corresponding branch throughout the lifetime of the script. So the `IF/ELSE` is evaluated at parse time and the resulting expression is used from that point on. Similar to the parse time vs run time example here: [Metaprogramming · The Julia Language](https://docs.julialang.org/en/v1/manual/metaprogramming/index.html#Hold-up:-why-macros?-1)

---

<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: [December 18, 2018, 10:33am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/10 "2018-12-18T10:33:40Z")

</div>

If you use a global `const`, the compiler should just eliminate the dead branches for you costlessly. Especially if you dispatch on type.

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [December 18, 2018, 10:43am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/11 "2018-12-18T10:43:57Z")

</div>

Constant propagation seems to be already enough for an inlineable function, as long as the global is a const:

```julia
doit(f, bool) = bool ? f() : f() + 22
const async_flag = true
function test()
  doit(()-> 22, async_flag)
end
@code_warntype test()
Body::Int64
163 1 ─ return 22 

```

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 18, 2018, 11:00am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/12 "2018-12-18T11:00:51Z")

</div>

Interesting - wondering how does that work, given that Julia allows changing the value of the `const`? I presume the function will be recompiled when that happens?

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 18, 2018, 11:05am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/13 "2018-12-18T11:05:07Z")

</div>

Oh, yes, that’s a good point. They’re not actually constants but fields in a config object. I could se tup some key constants, like `const DEBUG = config.debug`. Or maybe just refactor the config type to be immutable - that should have a similar effect as the constants, I expect.

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [December 18, 2018, 11:05am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/14 "2018-12-18T11:05:43Z")

</div>

No, that’s exactly why you get a warning when redefining a `const` - because you need to manually recompile a function to see any new `const`!

---

<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: [December 18, 2018, 11:06am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/15 "2018-12-18T11:06:46Z")

</div>

I am not sure (though it may not be “undefined” and just happens to work below).

```julia
julia> VERSION
v"1.2.0-DEV.28"

julia> const A = 1
1

julia> f() = A
f (generic function with 1 method)

julia> const A = 2
WARNING: redefining constant A
2

julia> f()
2

```

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [December 18, 2018, 11:13am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/16 "2018-12-18T11:13:22Z")

</div>

No:

```julia
julia> const A = 1
1

julia> f() = A
f (generic function with 1 method)

julia> f()
1

julia> const A = 2
WARNING: redefining constant A
2

julia> f()
1

```

as `f` only gets compiled when called.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [December 18, 2018, 4:01pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/17 "2018-12-18T16:01:19Z")

</div>

That’s very interesting. Looks like a closure and quacks like a closure, doesn’t it?

---

<div class="post-metadata">

### Author: ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)
#### Post date: [September 9, 2021, 2:13pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/18 "2021-09-09T14:13:34Z")

</div>

here’s a more efficient, in terms of code generation, macro to optionally apply another macro:

```julia
macro maybethread(flag, loop)
    if flag
        return quote Threads.@threads $loop; end
    else
        return quote $loop; end
    end
  end

```

thanks so much @jlapeyre for your example above.

@Tamas_Papp i did not see a way to optionally thread a loop with closures. would be curious about such an alternative solution if you have one.

EDIT: i realize now a huge limitation here is that `flag` has to be literally `false` or `true` and can NOT be a boolean variable ☹

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [September 9, 2021, 6:23pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/19 "2021-09-09T18:23:19Z")

</div>

I was actually recently trying to figure out this exact case of making `@threads` optional, based on a flag passed to a function. Would the macro you’re proposing be applicable for something like the following?

```julia
function func(args...; use_threads=false)
    @maybethread use_threads for i = 1:10
         do_something_with(i, args...)
    end
end

```

If not, is there a macro that would work for this kind of use case?

---

<div class="post-metadata">

### Author: ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)
#### Post date: [September 9, 2021, 7:34pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/20 "2021-09-09T19:34:48Z")

</div>

i don’t know how to pass in a variable without duplicating the loop code-gen. so instead, i’m now testing an alternative where a global `use_threads` is defined.

in my case, the loop is actually bit slower if i haven’t started julia with the `-t` flag, so i also check for that and skip the `@threads` macro if there is just one thread.

```julia
macro maybethread(loop)
  if use_threads && Threads.nthreads()>1
    return quote Threads.@threads $loop; end
  else
    return quote $loop; end
  end
end

```

[Next page](https://discourse.julialang.org/t/optional-macro-invocation/18588.md?page=2)
