# Compile time conditions or dispatch removing code based on (DEBUG, LIVE) mode

**URL:** <https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134>\
**Category:** General Usage\
**Created:** [October 23, 2022, 8:14am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134 "2022-10-23T08:14:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [October 23, 2022, 8:14am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/1 "2022-10-23T08:14:43Z")

</div>

Hey Julianners!  
**Conditional code compilation would be Crazy!**  
I want to make a code where I don’t have to comment out some of my code when I run my code in live version. I know I am talking about 10-20 conditions only but if certain part run millions of time it would be nice to avoid it. This would also open some chance to create more conditions to check the code with special flags, which is actually really big deal.

I saw we have `@static if [condition] [code] end` way to do it.  
What I wanted to know if I can achieve this effect on local variables. Dispatching on Val(:SYMBOL) wasn’t actually removing code. Which is actually really interesting that I cannot use `@inline` with the Val to remove codes from my codebase.

The code I tried without success:

```julia
using InteractiveUtils

@inline test(::Val{:DOTEST}, v) = v== 5.2 ? println("HEY") : println("NO")
@inline test(::Val{:NOTEST}, v) = nothing
eisdebug=false
fn1(isdebug, v) = begin
	test(isdebug, v)
	@static if eisdebug test(isdebug, v) end # works but only on global scope variables? 
end
fn1(Val(:DOTEST), 7.2)
fn1(Val(:NOTEST), 7.2)
@code_warntype fn1(Val(:DOTEST), 7.2)
@code_warntype fn1(Val(:NOTEST), 7.2)

```

```julia
using Static
@inline test2(::True, v) = v== 5.2 ? println("HEY") : println("NO")
@inline test2(::False, v) = nothing
fn2(isdebug, v) = begin
	test2(isdebug, v)
end

fn2(static(true), 7.2)
fn2(static(false), 7.2)
@code_warntype fn2(static(false), 7.2)
@code_warntype fn2(static(true), 7.2)

```

So how to avoid code to compile based on LOCAL fn variables like `@static`. (Supposed, we know the type exactly at compile time)

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [October 23, 2022, 9:02am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/3 "2022-10-23T09:02:58Z")

</div>

So there is another problem. `@static` seems to has some compilation problem as changing the global variable’s value doesn’t start recompilation as local variable would at type dispatch I guess.

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [October 24, 2022, 6:19am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/4 "2022-10-24T06:19:18Z")

</div>

Not really sure if this is useful to you, but maybe you can use the type system as a trait. Here’s a simple example to get you started.

```julia
abstract type CompileModeType end
struct Debug <: CompileModeType end
struct Live <: CompileModeType end

CompileMode() = Live()

test(v) = test(CompileMode(), v)
test(::Debug, v) = v == 5.2 ? "HEY" : "NO"
test(::Live, v) = nothing

test(7.2)
@code_warntype test(7.2)

```

You could add type arguments to CompileMode() for finer control.

See [Holy Traits Pattern (book excerpt)](https://ahsmart.com/pub/holy-traits-design-patterns-and-best-practice-book/), or search for Holy Traits for more detailed examples.

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [October 24, 2022, 8:45am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/5 "2022-10-24T08:45:06Z")

</div>

Hey,  
The problem is that, it is no different than the first example with the :DOTEST and :NOTEST, but it doesn’t require to create new structures for the solution.

You get this:

```julia
MethodInstance for test(::Float64)
  from test(v) in Main at /home/hm/repo/agei/tests/playground/compilation_time_condition.jl:45
Arguments
  #self#::Core.Const(test)
  v::Float64
Body::Nothing
1 ─ %1 = Main.CompileMode()::Core.Const(Live())
│ %2 = Main.test(%1, v)::Core.Const(nothing)
└── return %2

```

So, the point I want to make to not having these code in the code:

```julia
1 ─ %1 = Main.CompileMode()::Core.Const(Live())
│ %2 = Main.test(%1, v)::Core.Const(nothing)

```

Best,  
Marcell

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [October 24, 2022, 8:51am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/6 "2022-10-24T08:51:18Z")

</div>

Ok, just to note.  
Anyone else facing with this issue.

Each of the solution listed here is good.

1. The @static if … remove the appropriate code from the compilation.
2. In each of the other case you have to check the optimised compiled version, where the branch will be already excluded like this:

```julia
println(@code_typed fn1(Val(:DOTEST),7.2))
@code_typed fn1(Val(:NOTEST),7.2)

```

Result:

```julia
CodeInfo(
1 ─ %1 = Base.eq_float(v, 5.2)::Bool
└── goto #3 if not %1
2 ─ invoke Main.println("HEY"::String)::Nothing
└── goto #4
3 ─ invoke Main.println("NO"::String)::Nothing
└── goto #4
4 ┄ return nothing
) => Nothing
CodeInfo(
1 ─ return nothing
) => Nothing

```

So, the solution is actually fairly simple and can be chosen as preferred.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 24, 2022, 9:30am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/7 "2022-10-24T09:30:41Z")

</div>

Note that you can also use the “use functions as global variables” trick.

```julia
mode() = :debug

function myfunc()
    if mode() == :debug
        # do this only in debug mode
        println("debugging...")
    end
    println("regular computation")
end

```

This gives

```julia
julia> myfunc()
debugging...
regular computation

julia> @code_typed myfunc()
CodeInfo(
1 ─ goto #3 if not true
2 ─ invoke Main.println("debugging..."::String)::Any
3 ┄ %3 = invoke Main.println("regular computation"::String)::Nothing
└── return %3
) => Nothing

```

Redefining, say, `mode() = :live` will automatically trigger recompilation of `myfunc()` and, via constant propagation, eliminate the debug branch entirely:

```julia
julia> mode() = :live
mode (generic function with 1 method)

julia> myfunc()
regular computation

julia> @code_typed myfunc()
CodeInfo(
1 ─ nothing::Nothing
│ %2 = invoke Main.println("regular computation"::String)::Nothing
└── return %2
) => Nothing

```

One advantage of this approach compared to attempting to achieve the same with global variables is that you can’t assign variables in other modules but you can redefine functions in other modules. See [GitHub - JuliaPerf/STREAMBenchmark.jl: A version of the STREAM benchmark which measures the sustainable memory bandwidth.](https://github.com/JuliaPerf/STREAMBenchmark.jl#loopvectorization), where I tell the user to redefine `STREAMBenchmark.avxt() = true` to make my package STREAMBenchmark use LoopVectorization for multithreading, as an example.

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [November 27, 2022, 11:50am UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/8 "2022-11-27T11:50:54Z")

</div>

I realised `@static if` is actually useful if there can be structural differences or unexisting function that is called based on version or config and would cause compile time issues.

The question is whether it is better to have in precompilation time or better to have to do this job with the llvm optimizer or something like that.  
It would be great to know what is better when we calculate the time but… for now we have to be satisfied with these answer I guess.

Maybe one reason to only use `@static if` in very specific cases as it doesn’t perform recompilation with Revise when the if condition changes and drastically lower the speed of development as we need to make manual modification to start the recompilation.

---

<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 27, 2022, 2:59pm UTC](https://discourse.julialang.org/t/compile-time-conditions-or-dispatch-removing-code-based-on-debug-live-mode/89134/9 "2022-11-27T14:59:32Z")

</div>

[RFC: implement proper debug mode for packages (with support for re-precompilation) by KristofferC · Pull Request #37874 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/37874) might be relevant.
