inline void delay (int desired_delay) {
int i = 0;
while (i < desired_delay)
i++;
}
While "delay" is obviously an effect, it's not an effect in the PLT meaning of the word, since it causes no state changes to the program, and effect systems don't concern themselves with compute cost. The signal emission happens outside of the delay loop - usually inside some enclosing loop which obviously does have side-effects.This isn't quite correct, as demonstrated by the example of C++, because the act of turning a function that never halts (i.e. a function that is guaranteed to diverge) into a function that might halt is an observable effect. Rust actually relies on the fact that infinite loops are infinite, and they had to submit patches to LLVM to make it possible for languages to opt out of C++-style semantics: https://github.com/rust-lang/rust/issues/28728
Even in C++, it's uncommon for compilers to exploit it (especially in the trivial case) probably because, even if it's undefined, generally such behavior are pretty surprising and unexpected (and programmers do write infinite loops on purpose!).
Having non-effect producing infinite loops is useful (and sometimes is the only safe way of performing an operation), especially in some low level code. Another commenter pointed out the idea of delays in microcontrollers[3] but I want to provide an example from operating systems.
Take for example a panic function. At the end of it, you usually have an infinite loop of some sort, partly because you can't really safely do too much and panics generally represent a completely unrecoverable state from the operating system's point of view. A trivial
for (;;) {}
...is useful.[1]: For constant expressions. [2]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p28... [3]: https://news.ycombinator.com/item?id=40542860