Both of those things can be done in Rust, but not in safe Rust, you have to use unsafe APIs that don't check lifetimes at compile time. Safe Rust assumes a clear distinction between memory allocations that are still live and those that have been deallocated, and that you never want to access the latter, which of course is true for most applications.
It seems that in 2003 (when Fedora Linux first launched) this project was pretty obscure and early-stage, so it's hard to blame Red Hat for not having known about it then. This kind of thing just happens sometimes.
Fedora and Red Hat aren't super common or easily accessible anymore either, since they've made their choice as they're entitled to move towards enterprise.
I feel like fedora is pretty accessible at this point. The main speedbump is enabling non-free repos but if you're helping someone install linux for the first time you just tell them to check that box during setup.
The finalist authors' identities were revealed in October when the contest ended. This post is by Chris Finkle of https://tereglith.substack.com. Scott Alexander didn't write any of this year's entries.
Yes, I read the article back then, it's just came to my interest what there are multiple submissions at the same time (and now again) on a very... obscure topic.
Some commenters allege that the author and his father prepared the instant mashed potatoes wrong; in particular, they dumped boiling water directly onto the flakes, which the directions on the package say not to do.
An important part of the story here, not mentioned in this post but noted elsewhere (https://www.prisma.io/blog/from-rust-to-typescript-a-new-cha...), is that they gave up on offering client libraries for languages other than JavaScript/TypeScript. Doing this while mostly sharing a single implementation among all languages was much of the original reason to use Rust, because Rust is a good "lowest common denominator" language for FFI and TypeScript is not; it wasn't entirely about performance. If they hadn't tried to do this, they would likely never have used Rust; if they hadn't given up on it, they would likely still be using Rust.
Yeah, the whole point of Prisma 2 was to be multi language and multi-DB with a Rust server in between you and the DB. There are a lot of advantages to that approach in enterprise. You can do better access control, stats, connection pooling, etc (Formal is a YC company in that space). Prisma 1 was a scala implementation of that vision.
Anyway, end of an era. There were a couple community bindings in Python and Java that are now dead I assume. I was heavily invested in Prisma around 4-5 years ago, that is funnily enough what got me started on my Rust journey.
I suspect that this would result in a lot of .unwrap() calls or equivalent, and people would treat them as line noise and find them annoying.
An approach that I think would have most of the same correctness benefits as a proper sum type while being more ergonomic: Have two float types, one that can represent any float and one that can represent only finite floats. Floating-point operations return a finite float if all operands are of finite-float type, or an arbitrary float if any operand is of arbitrary-float type. If all operands are of finite-float type but the return value is infinity or NaN, the program panics or equivalent.
(A slightly more out-there extension of this idea: The finite-float type also can't represent negative zero. Any operation on finite-float-typed operands that would return negative zero returns positive zero instead. This means that finite floats obey the substitution property, and (as a minor added bonus) can be compared for equality by a simple bitwise comparison. It's possible that this idea is too weird, though, and there might be footguns in the case where you convert a finite float to an arbitrary one.)
> I suspect that this would result in a lot of .unwrap() calls or equivalent, and people would treat them as line noise and find them annoying.
I was thinking about this the other day for integer wrapping specifically, given that it's not checked in release mode for Rust (by default at least, I think there's a way to override that?). I suspect that it's also influenced by the fact that people kinda expect to be able to use operators for arithmetic, and it's not really clear how to deal with something like `a + b + c` in a way where each step has to be fallible; you could have errors propagate and then just have `(a + b + c)?`, but I'm not sure that would be immediately intuitive to people, or you could require it to be explicit at each step, e.g. `((a + b)? + c))?`, but that would be fairly verbose. The best I could come up with is to have a macro that does the first thing, which I imagine someone has probably already written before, where you could do something like `checked!(a + b + c)`, and then have it give a single result. I could almost imagine a language with more special syntax for things having a built-in operator for that, like wrapping it in double backticks or something rather than `checked!(...)`.
> Have two float types, one that can represent any float and one that can represent only finite floats. Floating-point operations return a finite float if all operands are of finite-float type, or an arbitrary float if any operand is of arbitrary-float type. If all operands are of finite-float type but the return value is infinity or NaN, the program panics or equivalent.
I suppose there's precedent of sorts in signaling NaNs (and NaNs in general, since FPUs need to account for payloads), but I don't know how much software actually makes use of sNaNs/payloads, nor how those features work in GPUs/super-performance-sensitive code.
I also feel that as far as Rust goes, the NonZero<T> types would seem to point towards not using the described finite/arbitrary float scheme as the NonZero<T> types don't implement "regular" arithmetic operations that can result in 0 (there's unsafe unchecked operations and explicit checked operations, but no +/-/etc.).
Rust's NonZero basically exists only to enable layout optimizations (e.g., Option<NonZero<usize>> takes up only one word of memory, because the all-zero bit pattern represents None). It's not particularly aiming to be used pervasively to improve correctness.
The key disanalogy between NonZero and the "finite float" idea is that zero comes up all the time in basically every kind of math, so you can't just use NonZero everywhere in your code; you have to constantly deal with the seam converting between the two types, which is the most unwieldy part of the scheme. By contrast, in many programs infinity and NaN are never expected to come up, and if they do it's a bug, so if you're in that situation you can just use the finite-float type throughout.
> By contrast, in many programs infinity and NaN are never expected to come up, and if they do it's a bug, so if you're in that situation you can just use the finite-float type throughout.
I suppose that's a fair point. I guess a better analogy might be to operations on normal integer types, where overflow is considered an error but that is not reflected in default operator function signatures.
I do want to circle back a bit and say that my mention of signaling NaNs would probably have been better served by a discussion of floating point exceptions more generally. In particular, I feel like existing IEEE floating point technically supports something like what you propose via hardware floating point exceptions and/or sNaNs, but I don't know how well those capabilities are actually supported (e.g., from what I remember the C++ interface for dealing with that kind of thing was clunky at best). I want to say that lifting those semantics into programming languages might interfere with normally desirable optimizations as well (e.g., effectively adding a branch after floating point operations might interfere with vectorization), though I suppose Rust could always pull what it did with integer overflow and turn off checks in release mode, as much as I dislike that decision.
reply