zlacker

[return to "Nimony (Nim 3.0) Design Principles"]
1. esafak+uTb[view] [source] 2025-12-05 14:08:33
>>andsoi+(OP)
> "Modern" languages try to avoid exceptions by using sum types and pattern matching plus lots of sugar to make this bearable. I personally dislike both exceptions and its emulation via sum types. ... I personally prefer to make the error state part of the objects: Streams can be in an error state, floats can be NaN and integers should be low(int) if they are invalid.

Special values like NaN are half-assed sum types. The latter give you compiler guarantees.

◧◩
2. elcrit+zYb[view] [source] 2025-12-05 14:33:52
>>esafak+uTb
The compiler can still enforce checks, such as with nil checks for pointers.

In my opinion it’s overall cleaner if the compiler handles enforcing it when it can. Something like “ensure variable is initialized” can just be another compiler check.

Combined with an effects system that lets you control which errors to enforce checking on or not. Nim has a nice `forbids: IOException` that lets users do that.

◧◩◪
3. umanwi+a1c[view] [source] 2025-12-05 14:45:38
>>elcrit+zYb
> The compiler can still enforce checks, such as with nil checks for pointers.

Only sometimes, when the compiler happens to be able to understand the code fully enough. With sum types it can be enforced all the time, and bypassed when the programmer explicitly wants it to be.

◧◩◪◨
4. wavemo+Nhc[view] [source] 2025-12-05 15:56:33
>>umanwi+a1c
There's nothing preventing this for floats and ints in principle. e.g. the machine representation could be float, but the type in the eyes of the compiler could be `float | nan` until you check it for nan (at which point it becomes `float`). Then any operation which can return nan would return `float | nan` instead.

tbh this system (assuming it works that way) would be more strict at compile-time than the vast majority of languages.

◧◩◪◨⬒
5. Mond_+ygd[view] [source] 2025-12-05 20:22:59
>>wavemo+Nhc
This is a bit confused. You're saying `float`, but a float comes with NaN by default. Any float can take NaN values.

If you actually want the compiler to check this on the level of the type system, it'd have to be `NonNaNFloat | NaN`. Then you can check which one you have and continue with a float that is guaranteed to not be NaN.

But (importantly) a NonNaNFloat is not the same as a float, and this distinction has to be encoded in the type system if you want to take this approach seriously. This distinction is NOT supported by most type systems (including Rust's std afaik, fwiw). It's similar to Rust's NonZero family of types.

◧◩◪◨⬒⬓
6. wavemo+KQd[view] [source] 2025-12-05 23:55:47
>>Mond_+ygd
You keep talking about Rust, but I'm not referring to Rust. This thread is discussing a (hypothetical, as-yet undeveloped) type system for a new version of Nim.

Hypothetically, no, the float type would not admit NaNs. You would be prevented from storing NaNs in them explicitly, and operations capable of producing NaNs would produce a `float | nan` type that is distinct from float, and can't be treated like float until it's checked for NaN.

And I'm not sure why it's being discussed as though this is some esoteric language feature. This is precisely the way non-nullable types work in languages like Kotlin and TypeScript. The underlying machine representation of the object is capable of containing null values, yes, but the compiler doesn't let you treat it as such (without certain workarounds).

◧◩◪◨⬒⬓⬔
7. Mond_+nye[view] [source] 2025-12-06 08:43:09
>>wavemo+KQd
Huh? Rust is just an example here. What I am saying is that you're just redefining float to mean NonNaNFloat.

This is fine, I guess, but it will cause a bunch of problems since e.g. Division of two floats has to be able to return NaNs. At that point you either need to require a check to see if the value is NaN (inconvenient and annoying) or allow people to just proceed. Not sure I am exactly sold on this so far.

◧◩◪◨⬒⬓⬔⧯
8. wavemo+Fcf[view] [source] 2025-12-06 15:46:23
>>Mond_+nye
Nobody's trying to sell you on anything. You again seem to be out-of-context with respect to the discussion being had.

The parent commenter stated that sum types work differently from a hypothetical float / NaN split, because compilers can't always "understand the code fully enough" to enforce checks. I simply responded that that is not true in principle, since you could just treat non-nan floats the same way that many languages treat non-null types.

Indeed, everything you're describing about non-nan floats applies equally to sum types - you can't operate on them unless you pattern match. You're highlighting the exact point I'm trying to make!

The fact that you consider this system "inconvenient", is entirely irrelevant to this discussion. Maybe the designer of Nim simply cares more about NaN-safety than you or I do. Who knows. Regardless, the original statement (that sum types and non-nan floats can't work the same way) is incorrect.

[go to top]