Asserts are convenient, but every time I encounter them I ask "Can the compiler prove this can't happen?" In the example of "min(ages) > 0", making age a NonZero type renders the assert unnecessary. Rust even has some fancy perf optimizations it can do with that information. It's a win all around.
If you created a custom NonZero type, how would the Rust compiler figure out how to optimize that? How would one communicate properties/traits of a custom type (like a non-zero unit) that a compiler can leverage to optimize ( in general, for any programming language )?
Rust's Two Kinds of 'Assert' Make for Better Code
21–30 of 87 posts
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#22Is it common to use parenthesis for python assert statements?
tratt might also be doing that more for consistency with the desugaring than as a routine behaviour.
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#23Asserts are convenient, but every time I encounter them I ask "Can the compiler prove this can't happen?" In the example of "min(ages) > 0", making age a NonZero type renders the assert unnecessary. Rust even has some fancy perf optimizations it can do with that information. It's a win all around.
If you created a custom NonZero type, how would the Rust compiler figure out how to optimize that? How would one communicate properties/traits of a custom type (like a non-zero unit) that a compiler can leverage to optimize ( in general, for any programming language )?
In rust might be a NewType: https://www.howtocodeit.com/articles/ultimate-guide-rust-new...
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#24I see asserts as a less temporary version of print() based debugging. Sometimes very useful as a quick and dirty fix, but 9 times out of 10 you’re better off with some combination of a real debugger, unit tests, tracing/logging, and better typing or validation.
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#25Common Lisp does assertions right: you can let ` assert ' provide a restart which allows the user to fix a problem when it crops up. For example: (assert ( That will print a message when the index is too large and give you the option of providing another index.
It would be interesting if a language allowed control flow to jump between catches and exceptions with named sort of exceptions. E.g., imagine in this example that the code code throw an invalid index exception, some calling code could catch that, and supply a new index, and control flow would resume from the throw expression. This would be a complete mess, but it would be interesting nonetheless :)
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#26> These days I thus view asserts as falling into two categories: > 1. Checking problem domain assumptions. > 2. Checking internal assumptions. (1) is the category of assert that should not be an assert . That is an error to be handled, not asserted. Ok, to be fair, (1) is really a combination of two categories: (1a) assumptions about uncontrolled external input, and (1b) assumptions about supposedly controlled or kno…
For fuzz testing I go even further with asserts. I usually also write a function called dbg_check(), which actively goes through all internal data and checks that all the internal invariants hold. Eg, in a b-tree, the depth should be the same for all children, children should be in order, width of all nodes is between n/2-n, and so on.
If anything breaks during fuzz testing (which is almost guaranteed), you want the program to crash as soon as possible - since that makes it much easier to debug. I'll wrap a lot of methods which modify the data structure in calls to dbg_check, calling it both before and after making changes. If dbg_check passes before a function runs, but fails afterwards - then I have a surefire way to narrow in on the buggy behaviour so I can fix it.
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#27Assertions are basically opposite to that. Useless in development because you watch/test closely anyway and useless in “release” because they vanish.
As I rarely write #CLK-level performance-required code - like most developers I believe - and mostly create systems that just do things rather than doing things in really tight loops many times a second, I always leave as much debug info and explicit failure modes as it is reasonable in my production code, so that the few-weeks failure would be immediate and explained in the logs (“reasonable” being readable without holding pgdn and not filling the ssd just after a week). It doesn’t mean that the system must crash hard as in sigsegv, ofc. It means it reports and logs all(!) steps and errors as they occur in a form that is obviously greppable by all important params (client id, task id, module tag, etc), and it stops a logical process in which an inconsistency occurred from advancing it further. If someone asks you later why it happened or what happened at the specific time with a specific process, you always have the answer almost immediately.
Tldr. Unless you write performance-first systems, i.e. you have performance requirements document in any form to follow, don’t turn off assertions and do log everything. You’ll thank yourself later.
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#28Earlier quoted context omitted.
It would be interesting if a language allowed control flow to jump between catches and exceptions with named sort of exceptions. E.g., imagine in this example that the code code throw an invalid index exception, some calling code could catch that, and supply a new index, and control flow would resume from the throw expression. This would be a complete mess, but it would be interesting nonetheless :)
That is literally what Common Lisp has and GP describes… https://en.m.wikibooks.org/wiki/Common_Lisp/Advanced_topics/...
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#29> These days I thus view asserts as falling into two categories: > 1. Checking problem domain assumptions. > 2. Checking internal assumptions. (1) is the category of assert that should not be an assert . That is an error to be handled, not asserted. Ok, to be fair, (1) is really a combination of two categories: (1a) assumptions about uncontrolled external input, and (1b) assumptions about supposedly controlled or kno…
Re: Rust's Two Kinds of 'Assert' Make for Better Code
#30For instance, if you assert that an incoming index into a function is within the bounds of a vector, then during the rest of the function the compiler can elide any bounds checking.