Defensive programming & assert


I come from the C++ world and I would like to use Julia more often. I generally use a lot of asserts in my code (a “defensive” programming approach), for instance imagine a function reading the first N records of a file. In pseudo C++ code you have something like:

 // read N first records
 void read_file_N(std::istream& file_in,const int N) 
      assert(N>=0);       // logical error: coder/caller responsibility is involved

      for(i=0;i<N;i++) {
           file >> data;

           // coder/caller responsibility is _not_ involved (I/O error)
           if(!data.well_formed())  { 
                throw error("Error in file, data is not well formed"); 

There are (at least) two kind of errors. Logical ones, involving coder responsibility and errors (like corrupted I/O etc.) where coder is not responsible. For the first ones I use a lot of asserts, for the second one I use exceptions. In C/C++ I can easily remove the assert thanks to a compiler flag (-DNDEBUG) thus there is no run-time penalty in production code. However, when I code in Julia (I am quite new with this language) I have the feeling that these two notions are mixed and that we can not take the same approach: AFAIK Julia @assert/assert is close to my C++ exception usage, but there is no Julia equivalent to C++ assert. This is a real problem for me and the way I code.

Do I miss something?
What can I do to have a C/C++ equivalent to assert in Julia (with the constraint that we can remove them in production code)?


you can use something like:

module MyModule
const DNDEBUG =  true
macro c_assert(boolean)
    if DNDEBUG
        :($boolean || error("Assertion $($a) == $($b) failed"))

julia> using MyModule
julia> @c_assert 1 == 2
ERROR: Assertion 1 == 2 failed

With DNDEBUG = false

julia> test() = @c_assert 1 == 2
test (generic function with 1 method)
julia> test()
julia> @code_llvm test()
define void @julia_test_69494() #0 !dbg !5 {
  ret void

Note, that this will recompile the optimized version as well, when you change the flag in the source.


Thanks for the feedback (and sorry for my first post bad formatting).
I was thinking to something similar but I thought that maybe there was a special/intergrated Julia way for it.

I think that there is a typo, the macro should be something like

:($boolean || error(“Assertion $boolean failed”))

but this only print “false”, how to print it in its unevaluted form?


Ah yeah, I first had another version.

julia> macro c_assert(boolean)
           if DNDEBUG
               :($(esc(boolean)) || error("Assertion $($(QuoteNode(boolean))) failed"))


Works great, thanks!


A little less magical:

macro c_assert(boolean)
      if DNDEBUG
           message = string("Assertion: ", boolean, " failed")
           :($(esc(boolean)) || error($message))


Reference: omit assert under --optimize; introduce@check macro?


Yes, I have seen that however on my Julia V0.6, @check macro is not found.


Indeed it hasn’t been implemented yet, but it is a popular wanted feature, I’d love built-in support too, just wanted people reading this know.


This is my take on this thread / issue:


Here’s a way this can be done for modules without breaking precompilation.

module DebugAsserts

export debug_asserts, @dassert

function debug_asserts(m::Module, dodebug::Bool)
    m.eval(:(_debug_enabled() = $dodebug))

# Like @assert, but only active in debug mode
macro dassert(exs...)
    if !isdefined(__module__, :_debug_enabled)
        eval(__module__, :(_debug_enabled() = false))
        if $__module__._debug_enabled()
            @assert $(map(esc,exs)...)



AFAIU, The way this works is exploiting that #265 (reliable redefinition of methods) is fixed, this automatically recompiles all dependent functions that use @dassert every time debug_asserts is called. Depending on how many functions uses @dassert (or how many functions are in the call graph of any function that uses it) this will have to recompile a different number of functions but, in the worst case, using debug_asserts will cause a full recompilation of the whole package.


That’s right, this relies on the compiler to recompile all methods which use @dassert when the associated _debug_enabled is redefined via #265. You can use this @dassert in your own package exactly the same way as @assert, but the expression should be completely optimized away unless you call debug_asserts(MyModule, true).


Ah, clever. And since we don’t print the method replacement warning anymore, seems like this should be fairly seamless even too. I’m not sure we would want to put a trick like that in Base (to avoid potential confusion over when world-age changes become visible), but on-the-other-hand, it’s such a simple mechanism (and world-age visibility constraints usually aren’t too noticeable), so perhaps, why not!