# 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:** 2\
**Page:** 2

<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 10, 2021, 2:45am UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/21 "2021-09-10T02:45:25Z")

</div>

I suppose one fundamental distinction is whether you want to make the threads optional at runtime vs at compile time. I think you (and the OP) were primarily looking for a compile-time switch, whereas I’m looking for a runtime switch.

Based on [@jlapeyre’s answer](https://discourse.julialang.org/t/optional-macro-invocation/18588/2), it occurred to me that maybe the easiest way to do this for `@threads` is to just modify the definition of the macro from the standard library. Indeed, the following seems like it works perfectly for me:

```julia
module ConditionalThreads

using Base.Threads
using Base.Threads: threadid, threading_run

macro threadsif(cond, loop)
    if !(isa(loop, Expr) && loop.head === :for)
        throw(ArgumentError("@threadsif requires a `for` loop expression"))
    end
    if !(loop.args[1] isa Expr && loop.args[1].head === :(=))
        throw(ArgumentError("nested outer loops are not currently supported by @threadsif"))
    end
    quote
        if $(esc(cond))
            $(Threads._threadsfor(loop.args[1], loop.args[2], :static))
        else
            $(esc(loop))
        end
    end
end

end

```

I’ve left out the `schedule` from the [original implementation](https://github.com/JuliaLang/julia/blob/1b93d53fc4bb59350ada898038ed4de2994cce33/base/threadingconstructs.jl#L118-L144) for conciseness since that’s currently limited to `:static` anyway. It wouldn’t be hard to add that back in.

**Edit** (usage example):

I currently have the above macro definition “in production” at [QuantumControlBase.jl](https://github.com/QuantumControl-jl/QuantumControlBase.jl/blob/0442a21c6fb6ae668c357d6a94d4b44f914274ea/src/conditionalthreads.jl), and it is used e.g. here:

[https://github.com/QuantumControl-jl/Krotov.jl/blob/a13206335003384cda41f2d5279e8c87be241236/src/optimize.jl#L303-L310](https://github.com/QuantumControl-jl/Krotov.jl/blob/a13206335003384cda41f2d5279e8c87be241236/src/optimize.jl#L303-L310)

---

<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 29, 2021, 8:33pm UTC](https://discourse.julialang.org/t/optional-macro-invocation/18588/22 "2021-09-29T20:33:07Z")

</div>

version 2 of my `maybethread` macro above, which optionally threads at compile time, is now hygienic:

```julia
macro maybethread(loop)
  if use_threads
    quote Threads.@threads $(Expr(loop.head,
                             Expr(loop.args[1].head, esc.(loop.args[1].args)...),
                             esc(loop.args[2]))); end
  else
    # @warn "running single threaded"
    quote $(esc(loop)); end
  end
end

```

i typically define `use_threads = Threads.nthreads()>1`.

thanks @[chakravala](https://discourse.julialang.org/u/chakravala) for [your post](https://discourse.julialang.org/t/calling-a-macro-from-within-a-macro-revisited/19680/12) which showed me how to do this.

figuring this out took a long time. maybe i’m stupid. maybe macros are hard. but i wholeheartedly agree with @c42f that we should [rethink them](https://github.com/JuliaLang/julia/issues/37691) for julia 2.0.

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