Live data from Hacker News

My least favorite Rust type

ridiculousfish.com

191–200 of 298 posts

Re: My least favorite Rust type

#191
post #128

Earlier quoted context omitted.

It looks like you can't. You can create a Range out of it, but the range is not an iterator. If you look at the Range docs[0], you'll see that it only implements Iterator where its generic type (A) implements std::iter::Step. Going to the Step docs[1] you'll see that its only implemented by integer types and char. If Vec implemented Step, you could iterate over it. Also, if you're referring to the "contains" guessing…

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

What would you expect those values to be?

Re: My least favorite Rust type

#192
post #165

Given how general Range is, how does it even implement a len() which has the behavior in the article? (I tried looking into the documentation for this and came up short on Ranges even having len; I see it provides a TrustedLen to other things via a trait, but that seems unrelated, and it has some len related to an overload of one specific iterative type, but I feel like I must have misunderstood it.) Either it assume…

Range implements the ExactSizedIterator trait, and this is why you can call `(0..5).len()`. When you call len() the ExactSizeIterator just calls size_hint [1].

The size_hint is implemented here [2]. This is where the "start [1] https://doc.rust-lang.org/src/core/iter/traits/exact_size.rs...

[2] https://doc.rust-lang.org/src/core/iter/range.rs.html#500-55...

Re: My least favorite Rust type

#193
post #155

For literals, clippy will catch this by default: error: this range is empty so it will yield no values --> src/main.rs:2:9 | 2 | let x = 5..0; | ^^^^ | = note: `#[deny(clippy::reversed_empty_ranges)]` on by default = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges help: consider using the following if you are attempting to iterate over this range in…

May be worth moving to rustc, because that's not just bad style, that's incorrect code.

I don't disagree but it feels like the bulk of the likely problema would be when not dealing with literals.

Re: My least favorite Rust type

#194
post #144
post #138

Earlier quoted context omitted.

Yeah, this sounds like it could be fixed with a one-liner without any breaking changes: `impl Copy for Range where T: Copy {}`. That being said, I can understand why this might not necessarily be desirable for some people; Copy is generally reserved for types that are "small enough" that implicitly copying the bytes will be cheap enough to ignore. It might seem obvious that a struct containing two types that are Copy…

The reason this can't be done quite as you describe is outlined in the linked issue: if something implements both `Iterator` (as Range does) as well as `Copy`, then you can end up in situations where you accidentally end up copying an iterator you think you're mutating. A good example is provided here: https://github.com/rust-lang/rust/issues/48649#issuecomment-...

Hmm, interesting. I honestly don't think I've ever really used an iterator like that, but I can understand why that would be considered undesirable. It does seem like having Range implement IntoIterator rather than Iterator would probably have been best, but that's tough to fix now.

Re: My least favorite Rust type

#195
post #165

Given how general Range is, how does it even implement a len() which has the behavior in the article? (I tried looking into the documentation for this and came up short on Ranges even having len; I see it provides a TrustedLen to other things via a trait, but that seems unrelated, and it has some len related to an overload of one specific iterative type, but I feel like I must have misunderstood it.) Either it assume…

> Given how general Range is, how does it even implement a len() which has the behavior in the article?

len() is hidden in ExactSizeIterator, which is implemented for a bunch of Range specializations: https://doc.rust-lang.org/std/ops/struct.Range.html#impl-Exa...

Expanding the docs node and following the [src] link for len, we can see it's using ExactSizeIterator's default implementation, which invokes size_hint: https://doc.rust-lang.org/src/core/iter/traits/exact_size.rs...

ExactSizeIterator only requires Iterator: https://doc.rust-lang.org/src/core/iter/traits/exact_size.rs...

And sure enough, that's where size_hint is implemented in Range: https://doc.rust-lang.org/std/ops/struct.Range.html#impl-Ite... -> https://doc.rust-lang.org/src/core/iter/range.rs.html#515-52...

Which in turn relies on steps_between, which is implemented via macro for various integer types:

https://doc.rust-lang.org/src/core/iter/range.rs.html#240-24...

https://doc.rust-lang.org/src/core/iter/range.rs.html#360-37...

https://doc.rust-lang.org/src/core/iter/range.rs.html#388-40...

Re: My least favorite Rust type

#196
post #165

Given how general Range is, how does it even implement a len() which has the behavior in the article? (I tried looking into the documentation for this and came up short on Ranges even having len; I see it provides a TrustedLen to other things via a trait, but that seems unrelated, and it has some len related to an overload of one specific iterative type, but I feel like I must have misunderstood it.) Either it assume…

> how does it even implement a len() which has the behavior in the article?

It's from `ExactSizedIterator.len()` and is a specialization of the case where `Iterator.size_hint()` returns known to be correct values.

It's a bit confusing on `Range` as it's not the distance between start/end or anything like that (well it's the number of steps when iterating Range so kinda the distance).

It also has the side-effect that it's not implemented for Range as I guess not to hinder 32bit compatibility (len/size_hint return a usize).

Because it's the iteration length it also is calculated based on iterations criteria, simplified `if start < end { end- start } else { 0 }`. Except in practice it goes from `len` to `size_hint` to the `Steps.steps_between` API in-lining all the calls and optimizing away the unnecessary overhead.

Re: My least favorite Rust type

#197
post #8

Why does Rust allow Ranges for types that don't have comparators in the first place?

Exactly my question. >If you try to enforce that start What even is a "range of non-comparable things"? Doesn't the very definition, included in the article, imply an ordering because of the "upper" and "lower" bounds? What on earth is a situation where "upper" is not necessarily greater than "lower"?

If you try to enforce start I mean consider:

`slice.get(start..end)`

against:

`(start..end).and_then(|range| slice.get(range))`

Re: My least favorite Rust type

#198

Earlier quoted context omitted.

Most of the methods are constrained to types that implement PartialOrd.

Yes, but why does Rust's Range type not require this?

You have no benefits from containing this.

No of the problems come from this not being constrained on PartialOrd. Instead they are related to other things like the usability benefit of range construction not being fallible (which is why we can't have a start Some things could be done differently by constraining the type to always be an integer, but expect `constains` now not needing a reference non of the thinks the article complained about would be different just by constraining it to an integer. In practice many of it's method are anyway only defined for some Range types like you can only use `Range` for slicing.

Re: My least favorite Rust type

#199

Earlier quoted context omitted.

Most of the methods are constrained to types that implement PartialOrd.

What happens if I make a range bounded on one end by NaN?

- Float ranges can't be used for indexing/slicing slices

- Float ranges don't implement Iterator

- Rust is clever enough to make is_empty checks NaN robust, so `is_empty` return true

- contains checks if it's inside the stard bound and inside the end bounds, but whichever of the bounds is NaN is always not inside the bounds and as such the range won't contain anything (which matches with the behaviour of is_empty)

So it works well.

But float ranges are kinda useless for anything but the contains/is_empty methods.

Re: My least favorite Rust type

#200

I can’t even figure out how to iterate over a Range of Vectors? iter and collect both don’t exist... Google doesn’t seem helpful either. I don’t know any rust but it seems unforgiving at the first hurdle here :-)

You can create a Range of nearly anything but that doesn't mean any of the methods/traits useful for a Range are implemented on it.

E.g. Iterator is only implemented for things implementing the currently unstable Step trait which for now are mainly integers and char.

E.g. only Range can be used to index/slice things.

Post reply on HN