Live data from Hacker News

My least favorite Rust type

ridiculousfish.com

291–298 of 298 posts

Re: My least favorite Rust type

#291

Earlier quoted context omitted.

There are a few things: - The big one is that, at least what I see from my admittedly flawed perspective, there appears to be an active annoyance by a significant number of participants on the various issues on the importance of maintaining library ergonomics under constrained execution environments, with bare metal / free-standing environments being an obvious scenario. An example that comes to mind being stuff deal…

That last one is a common enough idea nowadays. Prominent people in every community advocate enforcing code style rules (Douglas Crawford's Javascript linter is famous as an early example and gofmt is practically enforced in the community). The rest of the issues you mentioned are being actively worked on or investigated. Yes Rust 1.0 didn't solve all problems out of the gate and even now there's a lot of work still…

> That last one is a common enough idea nowadays. Prominent people in every community advocate enforcing code style rules (Douglas Crawford's Javascript linter is famous as an early example and gofmt is practically enforced in the community).

I would argue that this is because there are differences in the severity of the tooling. gofmt for example will not override your decisions regarding line breaks last time I checked, while rustfmt will not afford you any freedoms there.

Re: My least favorite Rust type

#292
post #236

Earlier quoted context omitted.

> I get a strong sense of Rust demanding that users subjugate themselves to all the choices and opinions of the architects I don't know why you feel that way. Any major language or standard library change goes through an RFC process, where anyone in the community can submit feedback, and from what I have seen, the official teams are very responsive to concerns.

There are a few things: - The big one is that, at least what I see from my admittedly flawed perspective, there appears to be an active annoyance by a significant number of participants on the various issues on the importance of maintaining library ergonomics under constrained execution environments, with bare metal / free-standing environments being an obvious scenario. An example that comes to mind being stuff deal…

> there appears to be an active annoyance by a significant number of participants on the various issues on the importance of maintaining library ergonomics under constrained execution environments

My understanding is that this is being worked on. Of course any language (or really any project) will have people annoyed that the maintainers priorities don't align perfectly with their priorities.

> What comes across as an almost begrudging foreign-function interface,

I haven't gotten any impression that FFI is begrudging. It really seems like a first class citizen to me, and is certainly better than the FFI story in say, java or go. Rust even has language features that exist just for FFI, such as unions and c-style variadic arguments.

> no ABI commitments

This is a recognized problem. It is also a hard problem, since lifetimes don't exist after compile time. But using the C-ABI is quite usable in some cases. And there have been a few RFCs around this recently (specifically around stable ABIs for vtables).

> lack of clarity about what is undefined behaviour under the `unsafe` operation needed to engage in any of this

This is again a known problem, and something that is improving.

> Cargo VS rustc and integration into other build systems.

I think there was some work being done on this, but I don't know the current status. There are people that use rust with bazel.

Re: My least favorite Rust type

#293
post #76
post #6

I feel like this is an example of what Jonathan Blow calls a "Big Idea" or a "100% solution". His thesis is that when you make a feature of a language too abstract and usable in many different contexts, eventually there will be so many corner cases that the result will almost certainly be clunky and full of footguns. He claims that language designers should aim for "80% solutions" instead, which cover most common usa…

> He claims that language designers should aim for "80% solutions" instead, which cover most common usages but limit themselves enough to avoid complexity. This runs in contrast to a lot of commonly accepted language design wisdom. This is easy enough to say, and indeed I do think it's a good approach, but the problem is identifying that 80% in the first place. The reason that language designers tend to favor general…

> With little time to observe use in the wild … the reasonable approach was to not over-constrain.

Given a new language feature and limited time to observe actual use, IMHO the reasonable approach would be to constrain it as tightly as possible. It's much easier to relax constraints to enable new uses later than it is to reign in inadvisable uses of an underconstrained interface. For example, if the original Range interface had simply consisted of two private, immutable fields with Copy + PartialOrd constraints and an implementation of the IntoIterator trait then it would be trivial to add setters (or public fields), an internal Iterator implementation, and looser type constraints later on if these were deemed necessary. Going the other way, however, breaks programs that have come to depend on these dubious features.

Re: My least favorite Rust type

#294
post #255

Earlier quoted context omitted.

That’s what I did (at repl.it anyway)... how do I print the values in a Range of Vectors?

You don't, because that doesn't make mathematical sense. Let's say I have the range [1].. [2], what is in this range? Well vectors are sorted in lexicographic order, so every vector that starts with 1. What comes after [1]? Suppose it's any vector whose first non zero digit is in place n (e.g. n = 2 and the vector is [1, 0, 3, 1]). I can make a vector that comes earlier in the ordering by just inserting another 0 (e.…

> there actually just isn't a well defined concept of next vector

I think there is a well-defined next vector, it just isn't very useful. The next vector after [1] for a vector of unsigned integers would have to be [1, 0]. And then [1, 0, 0], [1, 0, 0, 0], etc. (For signed integers substitute T::MIN instead of 0.)

Re: My least favorite Rust type

#296
post #176

Earlier quoted context omitted.

But why isn't it panicking on len()? How is 0 the right answer there?

Because that’s the length of the iterator? The range is empty, its exact size is 0.

The range is invalid, not empty; someone had to do a validity check to return 0 to prevent it from returning -5 or trying to count up from 0 (depending on what it was willing to assume). A big point of the article is that a range of size 0 should always be iterable, but it somehow isn't, because it isn't actually of size 0.

Re: My least favorite Rust type

#297

Earlier quoted context omitted.

Interesting: .len() is not the length of a slice induced by the range or the distance between start and end but instead it's the len method form `ExactSizedIterator`, which in turn is a "special case" of where `Iterator.size_hint()` is known to return a correct value. The thing is `Iterator.size_hint()` does return a size, which is usize. So `Range ` can only implement `ExactSizedIterator` on 64-bit targets, which I…

This is another Rust design mistake: conflating the platform pointer size with "lengths". It's possible to process files bigger than 4 GB on 32-bit platforms. It's even possible to memory map them (using sliding windows/views). In some Rust forums, the language designers were shocked to learn that this is possible. At any rate, the Range type was very clearly designed for slices of in-memory contiguous arrays. Then t…

Using pointer-sized sizes for in-memory collections and slices is no mistake, and every single Rust API involving file offsets or sizes in the Rust stdlib that I'm aware of uses u64 or i64, not pointer sized stuff. Perhaps you didn't mean to imply otherwise, but you do.

That iterators and ranges have this 1% edge case where you'll need to roll your own trait if you want "(0u64..1).len()" to compile because ExactSizedIterator was designed for the 99% case of in-memory collections, could be argued as a design mistake - or could be argued as a reasonable avoidance of overcomplication in std in favor of allowing the end users who encounter that edge case to solve the problem how they please, if it is indeed a problem for them.

    trait Len64 {
        fn len(&self) -> u64;
    }
    impl Len64 for std::ops::Range {
        fn len(&self) -> u64 { self.end - self.start }
    }
    fn main() {
        println!("{}", (0u32..!0).len());
        println!("{}", (0u64..!0).len());
    }
https://play.rust-lang.org/?version=stable&mode=debug&editio...

    4294967295
    18446744073709551615
Meanwhile, I'm still inheriting C/C++ codebases using APIs that know they're dealing with files and still use pointer-sized integers. In their defense, the system APIs they use often predate widespread 64-bit integer support in 32-bit C compilers (I'm looking at you, fseek/ftell). Less in their defense, the wrappers around said system APIs often postdate the very same, and postdate a slew of alternative APIs that don't even need 64-bit integer support.

Re: My least favorite Rust type

#298

Earlier quoted context omitted.

I think that's what you would expect. Why do you think it is strange?

I don't know, I just find the concept of lexicographically ordering vectors something that isn't really useful. Can you think of examples where this might be something you would want?

Yes, if your vector represents indices into a tensor for example. I have written code that does exactly that in C++.
Post reply on HN