4 ms·
Wait hold on, why are you jumping straight to "what the compiler can infer"? Compilers (and type systems) are written by and for humans, so first tell me the u
by dasil003 4y ago
Wait hold on, why are you jumping straight to "what the compiler can infer"? Compilers (and type systems) are written by and for humans, so first tell me the use case for multiplying a float by an int that does not lead to a float and justify why we should optimize for that case.
- fennecfoxen 4y agoSure. Multiplying a float by an int that leads to AN ERROR because you mixed up your types and you are now losing precision somewhere or other. Avoiding that sort of an error at compile-time is right there at the heart of the core premise of Rust, so Rust should optimize for it.
- Turing_Machine 4y agoExcept that in the real world people want to multiply floats by ints all the time, and they don't want to go through a lot of type-wankery to do it.
- RHSeeger 4y agoIn order to make _some_ things safer, every type system must make _other_ things impossible. There is, as far as I'm aware, no real way around that.
- fennecfoxen 4y agoIt’s like one cast, yo
- Turing_Machine 4y agoIt's "one cast" times the total number of times you need to multiple ints by floats for the rest of your career.
- civilized 4y agoYou can also make errors when you multiply two floats together. Why then should Rust allow any operations at all?
- lang_agnostic 4y agoYou simultaneously make a great and stupid point. The stupid part is obvious: operations are allowed because writing programs is useful. Now for the great, nuanced and complicated point: How do we detect errors when manipulating floats while allowing us to write the useful programs? This boils down to two things: 1. What do we think is correct at any given time for any given program? The compiler can't know so we have to tell it, which brings us to 2 2. How do we write down in our programming language what is supposed to be correct? The problem with floats is that sometimes you care about precision, sometimes you don't sometimes you care about overflows, sometimes you don't. Sometimes you care about inverse operations, sometimes you don't. Commercial programming language which only expose a "float" types usually are unable to deal with the greater complexity of _ensuring_ that some property you care about isn't broken. That is why compilers let you operate on floats and shoot yourself in the foot when you divide and then multiply back. On the other hand, one could imagine a future programming language (and some academic experiments already exist) where you can tell the computer "in this part of the code, it's important that I never overflow" or "in this function, I expect multiplication and division to be inverses of each other". In which case the compiler will display diagnostic information if you do something that break those properties. It's not clear yet what is the most convenient user interface to write down and check those properties. But many believe it by using even more advanced type systems than Rust. Many other believe that we can add static analysis atop existing programming languages to obtain the same result. TLDR: Rust allows it for now because 50-100years in the future we'll have to tools to tell when it's ok and when it's not ok to multiply floats together. Right now we're still smacking rocks together to make fire.
- ajxs 4y agoMost of the work I do in systems programming languages is bare-metal code where semantics for representing and manipulating data at the bit-level are required. I need to have very explicit control over the shape of the data in memory. For starters, many of the systems I work with don't even have the ability to do floating-point calculations at all. > "Compilers (and type systems) are written by and for humans..." The abstraction that is the type system might be designed for humans, but the underlying physical layers are totally non-abstract, tangible things with their own constraints. If I'm sending data to a DAC over the i2c protocol, the protocol has very real constraints at the electrical level. In order to interact with such protocols in a meaningful way we need low-level semantics to control the shape of data at the level of individual bits. Consider the following: uint32_t a = 1234567; float b = 0.34; uint8_t c = a * b; fwrite(&c, 1, 1, stream); What value gets written to the stream here? > "first tell me the use case for multiplying a float by an int that does not lead to a float" Should the Rust compiler forbid all multiplication between the two types that doesn't get stored in a float?
- pfdietz 4y agoOne can manipulate arbitrary precision integers at the bit level. Nonnegative integers correspond to infinite sequences of bits all but a finite number of which are 0; negative numbers to infinite sequences in which all but a finite number are 1. There's no need in most programs to insist that variables have some finite (and fairly small) range beyond which integer operations stop acting like their mathematical definition.
- nybble41 4y agoSure, if you want to use arbitrary-precision integers everywhere. At a significant loss in performance.
- ajxs 4y agoThere are very real use cases where integer types with specific fixed widths are necessary, on account of very real constraints. A serial interface for instance, which is a very common peripheral outside of PCs, often sends information out over the wire 8 bits at a time. 'Systems programming languages' need to specify how arithmetic using these fixed-width integers should work.
- Strilanc 4y agoI would say the issue is which float you want. If the int is larger than 2^24 it can't be represented exactly as a float32 so you may have intended to widen to float64 which covers int32 and float32. Or maybe not; maybe you wanted performance instead. That being said, multiplying by 2 not working is pretty funny because that's always exact until you overflow the float. It's pretty annoying the compiler didn't just figure out there was no precision loss anywhere here so just do it instead of complaining.
- Gibbon1 4y ago> I would say the issue is which float you want. You're getting warmer. The reality is compilers default floating point is wrong for most uses. You should be able to represent things like pi and 1/3 exactly by default. That that's not the case in JS is criminal.
- aw1621107 4y agoSo symbolic math? That sounds like an interesting choice of details. Is it something that would produce tangible better results in a significant number of cases?