-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
After a discussion on Julia-Users, it seems to me that at least some might agree with me that being able to turn off assertions could be a good idea. This is permitted in most languages, it seems. My suggestion is to follow the example of D, which I believe has made some sensible decisions on assertions and DbC in general. Their solution is to split assertions into two types, named assert and enforce. They then have a command-line switch named --release that turns off assert but leaves enforce in place. If we adopt such a switch, with an accessor similar to isinteractive(), it can be used also by others, similar to (but the negation of) the __debug__ variable in Python, which is set to True only if the -O switch is not supplied.
My suggestion is:
- Add the switch
--releaseat the Julia level (i.e., inclient.jl) with a subsequently available accessorisrelease(), which is exported, so it can also be used by others (though this is an ancillary benefit). - Rename
asserttoenforceand@assertto@enforce. - Introduce new versions of
assertand@assertthat useisrelease()to determine whether to become a no-op or to delegate toenforceand@enforce, respectively. This will not entirely eliminate the cost of calls toassert, of course—one will still need to evaluate the arguments and execute theif-statement, but it will eliminate the cost (and the functionality) of@assertin release code.
The idea, then, is to use assert and @assert more for testing purposes, debugging and for checking for programming errors, and to use enforce and @enforce for error handling and input checking, and for any other kind of assertions one would want to keep in the code, regardless of release status.
I have made a stab at implementing the switch, function and macro. Because the switch only takes effect once client.jl is loaded, I have renamed the uses of assert to enforce in base/ (renamed all uses, for consistency, though not strictly necessary), but I left the uses in test/ alone. (I have updated repl.c but not docs, manpage or helpdb.jl, for example. And I haven't added any tests, as I didn't find any for the original assertion functionality, and I'm not sure what infrastructure you'd want to use to test command-line switches…)
The new function/macro are defined as follows—which I believe is not entirely correct…
assert(x) = isrelease() ? nothing : enforce(x)
macro assert(ex,msgs...)
if isrelease()
:nothing
else
:(@enforce(($ex),($msgs)...))
end
endIt works for my simple ad hoc tests, but fails in, for example, test/bitarray.jl, where a call to @assert occurs inside another macro with an argument also named ex. I then get complaints on ex not existing. So I guess my quoting mojo isn't quite up to snuff, but I'm guessing this should be easy to fix? (Just calling @enforce gives me the wrong kind of return value, as far as I can see.)
Anyone interested in this? Should I submit a WIP pull request?