Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable @assert in Julia

Tags:

assert

julia

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?

like image 600
opus111 Avatar asked Oct 09 '19 13:10

opus111


2 Answers

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:

  • Method dispatch guarantees that the arguments to your functions are of the correct type.
  • You can avoid duplicating the same assertion across multiple functions foo(t::FiveMinuteMultiple), bar(t::FiveMinuteMultiple), and baz(t::FiveMinuteMultiple).
  • The more specific argument annotation alerts users and developers that the function expects a more specific type of data.

Disadvantages:

  • Depending on your use case, you may need to forward various methods to the data field within your struct. For example, for FiveMinuteMultiple you may need to forward methods such as day, hour, etc, to the t field of the struct.
  • Adding a new concept (type) to represent assertions about your data might introduce an unnecessary layer of abstraction.
like image 121
Cameron Bieganek Avatar answered Nov 19 '22 22:11

Cameron Bieganek


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)

like image 10
carstenbauer Avatar answered Nov 19 '22 22:11

carstenbauer