As an old C programmer, I use lots of asserts in my code. Now I want to globally switch them off to speed things up. What is the best practice way to do that?
As an old C programmer, I use lots of asserts in my code. Now I want to globally switch them off to speed things up. What is the best practice way to do that?
There is no built-in option / command line flag to disable @asserts globally, yet(!).
For now, you can define a @myassert macro which, depending on a global switch, is a no-op or a regular @assert:
asserting() = false # when set to true, this will enable all `@myassert`s
macro mayassert(test)
esc(:(if $(@__MODULE__).asserting()
@assert($test)
end))
end
f(x) = @mayassert x < 2
(taken from https://discourse.julialang.org/t/assert-alternatives/24775/14)
Although it would be nice to have this feature, the need for @asserts in your code can be reduced by defining and dispatching on your own types. For example, suppose you have a function foo(t::TimeType) = t, but you only want to accept times that are a multiple of five minutes. You can create a new type with this requirement:
using Dates
struct FiveMinuteMultiple
t::DateTime
function FiveMinuteMultiple(y, m, d, h, mi)
if mi%5 != 0
throw(DomainError(m, "the minute argument must be a multiple of 5"))
end
new(DateTime(y, m, d, h, mi))
end
end
Now you literally can't create a FiveMinuteMultiple that is not a multiple of five minutes:
julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 23)
ERROR: DomainError with 7:
the minute argument must be a multiple of 5
Stacktrace:
[1] FiveMinuteMultiple(::Int64, ::Int64, ::Int64, ::Int64, ::Int64) at ./REPL[2]:5
[2] top-level scope at none:0
julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 25)
FiveMinuteMultiple(2016-07-15T04:25:00)
So if you now define foo(t::FiveMinuteMultiple) = t, you no longer need an @assert to verify that the argument is a time that is a multiple of five minutes. Sure, you still have to pay the cost of argument checking when you construct the FiveMinuteMultiple, but unless it's a hot inner loop you probably want that additional data validation anyways.
Advantages:
foo(t::FiveMinuteMultiple), bar(t::FiveMinuteMultiple), and baz(t::FiveMinuteMultiple).Disadvantages:
FiveMinuteMultiple you may need to forward methods such as day, hour, etc, to the t field of the struct.You could put your @assert statements in a @debug block. Then the @assert call is desactivated, unless you activate debugging either globally (ENV["JULIA_DEBUG"] = "all") or just for your module (ENV["JULIA_DEBUG"] = "NameOfYourModule")
julia> @debug begin
@assert 1==2
end
#or
@debug @assert 1==2 # assert is not called
julia> ENV["JULIA_DEBUG"] = "all" # enable debugging
"all"
julia> @debug begin
@assert 1==2
end
┌ Error: Exception while generating log record in module Main at REPL[4]:1
│ exception =
│ AssertionError: 1 == 2
│ Stacktrace:
│ [1] top-level scope at REPL[4]:2
│ [2] top-level scope at logging.jl:319
| ...
└ @ Main REPL[4]:1