Live data from Hacker News

Rust's Two Kinds of 'Assert' Make for Better Code

tratt.net

11–20 of 87 posts

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#11
post #9

Common 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.

Wat's up with calling the variable "index" in the second parameter to assert? What happens when you try to call what's presumably an integer..?

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#12
post #11
post #9

Common 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.

Wat's up with calling the variable "index" in the second parameter to assert? What happens when you try to call what's presumably an integer..?

There is no call. assert is a macro, the second parameter is a list of places which the restart can update.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#13
post #9

Common 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

#14
Nim has this too:

  - `assert` is disabled in unsafe `danger` mode or can be disabled with a flag for performance
  - `doAssert` cannot be disabled
While I've never come across an argument for why there are two types of assert, over time I’ve naturally started using them in the same way as the author.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#15
post #13
post #9

Common 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 :)

Exceptions are a special case of general effect systems which do include the capability you describe.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#16

    > 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 known input. Both should be handled with error checking most of the time, but it's forgivable for (1b) to be asserted if it's too inconvenient to do proper error handling. (1b) and (2) are problems that you need to fix, and the sooner and clearer the issue is announced, the more likely and easier it is to be fixed.

One thing I didn't see mentioned is that asserts, especially category (2), enable fuzz testing to be vastly more effective. A fuzz test doesn't have to stumble across something that causes a crash or a recognizably bad output; it just needs to trigger an assert. Which is another reason to not use asserts for unexpected input; fuzzers are supposed to give unexpected input, and your program is supposed to handle it reasonably gracefully. If you over-constrain the input, then first you'll be wrong because weirdness will sneak in anyway, and second the fuzzer is harder to implement correctly and is less powerful. The fuzzer is supposed to be a chaos monkey, and it works best if you allow it to be one.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#17
"Using runtime assert() in a tight performance loop can impact performance?" Um, like ... duh?

Run time checks should simply be enabled. Normally, you're checking some context on entry or exit from a function. 99% of the time it simply won't matter to performance. And, when it does, it will pop out at you and you can remove it.

The bigger issue as alluded to is assert() in libraries. As a user, you can't add an assert() to a library. And also, as a user, you can't remove an assert() that is getting in your way.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#18

Nim has this too: - `assert` is disabled in unsafe `danger` mode or can be disabled with a flag for performance - `doAssert` cannot be disabled While I've never come across an argument for why there are two types of assert, over time I’ve naturally started using them in the same way as the author.

How are people still making the classic `foo`/`foo_safe_version` mistake? In a supposedly modern language. And they didn't even name the safe version clearly! If the rest of Nim is designed on this level then I hope it never succeeds.

Note that Rust got this exactly right. assert, debug_assert. Clear and fail-safe.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#19
post #3
post #2

> The problem that I’ve just expressed ultimately occurs because languages like C force us to encode both kinds of assumption with a single assert statement: either all asserts are compiled in or none are. It’s trivial to write a debug_assert macro in C, so no, you’re not forced to do that.

It says so in the last paragraph

Right, this whole debug_assert thing is just a tiny bit of syntactic sugar. Everyone starts their C/C++ programs with a dozen lines of #define that wouldn't be necessary if only the authors in the 1980s had the foresight to design programming languages to fit the taste of 2020s programmers. This eliminates one of those lines.

Rust provides some remarkably rich features to help you reason about the assumptions, preconditions and postconditions your code has, but debug_assert isn't one of them.

Re: Rust's Two Kinds of 'Assert' Make for Better Code

#20
post #13
post #9

Common 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 :)

That is literally what Common Lisp has and GP describes…

https://en.m.wikibooks.org/wiki/Common_Lisp/Advanced_topics/...

Post reply on HN