Skip to content

Implement direct usize indexing#132

Merged
cuviper merged 2 commits into
indexmap-rs:masterfrom
cuviper:direct-index
Aug 7, 2020
Merged

Implement direct usize indexing#132
cuviper merged 2 commits into
indexmap-rs:masterfrom
cuviper:direct-index

Conversation

@cuviper

@cuviper cuviper commented Jun 11, 2020

Copy link
Copy Markdown
Member
where
    IndexMap<K, V, S>: IndexMut<usize, Output = V>,
    IndexSet<T, S>: Index<usize, Output = T>,

This allows map[i] and set[i] indexing to access values directly,
panicking if the index is out of bounds, similar to slices.

On maps, this somewhat overlaps with Index<&Q> + IndexMut<&Q> where
Q: Equivalent<K>. The reference makes this indexing unambiguous, but
it could be confusing to users if the key type is also an integer.

@cuviper

cuviper commented Jun 11, 2020

Copy link
Copy Markdown
Member Author

In my experiments in rustc, replacing HashMap,Vec combinations with indexmap, I've found it annoying to replace direct vec[i] indexing with get_index(i).unwrap().1. I didn't find anywhere that we've considered Index<usize> before, but it would make this a lot easier.

@cuviper

cuviper commented Jun 11, 2020

Copy link
Copy Markdown
Member Author

One downside is that with my experiment of custom index types, I would ideally replace this Index<usize> with Index<Idx> for IndexMap<K, V, S, Idx>, but I can't prove that Index<Idx> and Index<&Q> are distinct. We could still allow Index<usize> with any Idx though.

@bluss

bluss commented Jun 28, 2020

Copy link
Copy Markdown
Member

I think we should just wait with this, in that case. If we have an indexing operator, IMO it must use the index type that we have parameterized the map with.

@cuviper

cuviper commented Jul 1, 2020

Copy link
Copy Markdown
Member Author

I brought this up in the forum: https://users.rust-lang.org/t/any-tricks-for-generic-overlap-with-references/45186

I now think the answer is that we shouldn't try to create generic Index<Idx> at all. Instead, we can just add concrete Index<usize> and Index<u32> for maps and sets of the corresponding index type. Then if a user has a newtype index, coherence will still let them write their own Index<MyIndex>, which just needs to call get_index and unwrap/expect.

@bluss

bluss commented Jul 2, 2020

Copy link
Copy Markdown
Member

That makes sense but

ith Index for IndexMap<K, V, S, Idx>, but I can't prove that Index and Index<&Q> are distinct

Won't we have a trait bound on Idx? If that's a local trait it should be enough, it will prove that no references implement it? (Or maybe that doesn't work because references are fundamental)

@cuviper

cuviper commented Jul 2, 2020

Copy link
Copy Markdown
Member Author

(Or maybe that doesn't work because references are fundamental)

I think that's it. I shared a simplified playground, if you want to experiment with it:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=161bde1feeaa8c4aaaa864636f2f2ae1

error[E0119]: conflicting implementations of trait `std::ops::Index<&_>` for type `Container<_, &_>`:
[...]
   = note: downstream crates may implement trait `AsIndex` for type `&_`

@cuviper

cuviper commented Jul 24, 2020

Copy link
Copy Markdown
Member Author

@bluss any more thoughts on this? My plan for custom index types is to just implement each manually, rather than trying to have a blanket impl that potentially conflicts with Index<&Q>.

impl<K, V, S> Index<usize> for IndexMap<K, V, S, usize> {...}
impl<K, V, S> Index<u32> for IndexMap<K, V, S, u32> {...}
// perhaps all unsigned integers
// users can do their own `Index<NewTypeIndex>`

cuviper added 2 commits August 7, 2020 14:45
```rust
where
    IndexMap<K, V, S>: IndexMut<usize, Output = V>,
    IndexSet<T, S>: Index<usize, Output = T>,
```

This allows `map[i]` and `set[i]` indexing to access values directly,
panicking if the index is out of bounds, similar to slices.

On maps, this somewhat overlaps with `Index<&Q> + IndexMut<&Q>` where
`Q: Equivalent<K>`. The reference makes this indexing unambiguous, but
it could be confusing to users if the key type is also an integer.
@cuviper

cuviper commented Aug 7, 2020

Copy link
Copy Markdown
Member Author

Let's go ahead with that plan then...

@cuviper
cuviper merged commit 8282873 into indexmap-rs:master Aug 7, 2020
@cuviper
cuviper deleted the direct-index branch July 18, 2023 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants