When is it okay to use `@assert`?

I see @assert used frequently in the wild to check function inputs, and it looks a lot nicer than putting a bunch of if/throw statements at the top of every function.

However, ModernJuliaWorkflows says:

To test the arguments provided to the functions within your code (for instance their sign or value), avoid @assert (which can be deactivated) and use ArgCheck.jl instead.

and @assert’s docstring says:

Warning
│ An assert might be disabled at various optimization levels. Assert
│ should therefore only be used as a debugging tool and not used for
│ authentication verification (e.g., verifying passwords), nor should
│ side effects needed for the function to work correctly be used
│ inside of asserts.

So,

  1. Why do I still see @assert in so many popular packages despite the warnings?
  2. Can’t we just update @assert to natively do whatever makes ArgCheck better?

It seems silly to tell people to go find external package tools because the built-in tools are not reliable enough. (I wonder similarly about @time and @btime.)

1 Like

because

An assert might be disabled at various optimization levels

never actually happens, despite the fact that the docs warn it might

4 Likes

||/&& are also really useful for these short error checks and not quite as large/tedious as the equivalent if block. They’re still longer than a naked @assert (with the auto-generated error message) but about as long as one with a custom message.

Like

x > 0 || throw(DomainError(x,"x must be positive"))
1 Like

@assert removal might happen at some point.

2 Likes

I personally do not like seeing Boolean logic for control flow like that. It seems like a computer science hack that is not very readable for mortals. Related Github Issue

I can’t really follow the discussion, but hopefully we get a suitable alternative before @asserts are just turned off!

p || error("p") or ArgCheck.@check are ways to write enforced checks.

Since @assert may be removed in future, you should avoid using @assert with side effects as an essential part the program flow. For example, code like this would be problematic:

v = [1, 2]
@assert pop!(v) == 2 # may stop working in future
println(last(v))

I don’t think the plan is to just turn them off, but rather to add flags or command-line options to allow a user to turn them on/off.