-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IndexAssign: overloading the a[b] = c
expression
#1129
Conversation
map[key] = value; // equivalent to `map.insert(key, value);` | ||
``` | ||
|
||
- Setting each element of a "slice" to some value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider different terminology. subset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, subset sounds better
Clarification request: is this RFC actually proposing we provide |
``` rust | ||
let mut matrix = { .. }; | ||
|
||
// Set each element of the second row of `matrix` to `1` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a distinct level of sugar-iness here that feels a bit unexpected to me in Rust - we've got a single expression on the right and we are setting multiple values on the left of the assignment. I don't think we should allow that (or at least we should not encourage it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sugar is common in languages aimed at numerical/scientific computing see NumPy, Julia and Matlab/Octave. It would be helpful for libraries that want to compete in the same space to be able to provide a similar syntax to ease adoption/porting.
I don't think that this form of sugar will become common in other areas/mainstream Rust.
No, the only proposed changes to the standard libraries are the ones to HashMap/BTreeMap. This syntax is stated as a potential use case for linear algebra libraries. See #1129 (comment) |
This basically LGTM from the what-collections-want perspective. I'm a bit squeemish about the example usages, but such is operator-overloading-lyfe. I don't think the interaction between IndexMut and IndexAssign are particularly worrying in practice, as the RFC notes. I'm gonna regret this but: why not IndexSet? This would pair more cleanly with the hypothetical IndexGet that e.g. BitVec wants. |
I agree with the general idea, but I’d very much prefer |
I'm sort of grouping (I'm actually fine with either name.) @P1start Now that you mention it, yes, it makes sense to reverse the priorities. I'll test that locally and let you know, but I don't expect any difficulties. |
It does seem a bit footgunny that |
I'm in favor of this RFC, because I view it as a special case of |
@pythonesque FYI, there's already an RFC about overloading all the other augmented assignment operators ( @sfackler Yeah. I don't know how much would help but if we give |
@P1start FYI, I tested changing priorities in this branch, and all test continue to pass. |
+1 And a small question: does |
It doesn't work in the current implementation, but given that What doesn't work and won't work with
Yes, if the macro expands to |
Thanks for another great RFC @japaric! I think the I am for this RFC, but also for recommending that any implementation of EDIT: Removed broken example code; it wasn't hugely enlightening anyway. |
If IndexAssign panics on missing keys, then it's basically useless. The whole point is that it's sugar for insertion. |
@gankro: It would be useless for standard maps. BitVec and the other use cases @japaric mentions (linear algebra etc) would stay. How about IndexAssign taking Cow? There would be no silent ambiguity, requiring
|
Are there any thoughts on how this interacts with placement-new? |
Regarding the I am interested in the comments by @Florob about placement-new, though. It's a good thing to consider. It's true that it might be nice to write cc @pnkfelix |
The notation |
@nikomatsakis That is unless the |
@bluss ah, ok, I see. You're right, I was overlooking that (or missed it). |
So it seems like basically the fate of this RFC boils down to the question of the "hashmap footgun", where If the footgun is a concern, one possible fix is to say that if we see an expression where |
ps I've not re-read the RFC so I apologize if I'm misremembering something. Just trying to get conversation going again here. I personally... think I prefer the "do not fallback to |
I think that seems reasonable to me. |
(Using type ascription syntax to illustrate.) None of the two ways presented to go about
|
One interesting subtlety is that IndexMut is potentially more efficient than IndexSet on maps: you don't need to maintain the state to maybe insert. I believe bluss's BTreeMap rewrite would nullify the difference (state need not be maintained because we have parent pointers). I believe any differences are also negligible for HashMap. |
I've updated the RFC! The main proposal is now the "no fallback" alternative proposed by @nikomatsakis.
@bluss Check the updated drawbacks section, I suggest using
@retep998 Could you post your use case(s) (and desired |
This is totally unrelated to the current RFC, but the use cases I see for |
@japaric https://github.com/NoLifeDev/nx-rs/blob/master/src/node.rs#L72-L92 |
@retep998 Thanks. In that case, indexing doesn't freeze trait IndexNoHKT<Idx> {
type Output;
/// `self[i]` === `self.index(i)`
fn index(&self, i: Idx) -> Self::Output;
}
trait IndexMutNoHKT<Idx> {
type Output;
/// `self[mut i]` === `self.index_mut(i)`
fn index_mut(&mut self, i: Idx) -> Self::Output;
}
// Your example
impl<'a, 's> IndexNoHKT<&'s str> for Node<'a> {
type Output = Option<Node<'a>>;
// `index` would be same as your `Node::get` method
} Plus the restriction that @sfackler mentioned: if you implement any of If we had HKT we could define a more general set of traits: trait IndexHKT<Idx> {
// Hypothetical syntax. This is a type constructor that takes a lifetime
// as input and returns a concrete type
type Output<'a>;
/// `self[i]` === `self.index(i)`
fn index<'s>(&'s self, i: Idx) -> Self::Output<'s>;
}
trait IndexMutHKT<Idx> {
type Output<'a>;
/// `self[mut i]` === `self.index_mut(i)`
fn index_mut<'s>(&'s mut self, i: Idx) -> Self::Output<'s>;
} These would let us implement indexing that does freeze Below, an example that can't be implemented with struct BoxedSlice<T>(Box<[T]>);
struct Slice<'a, T>(&'a [T]);
impl<T> IndexHKT<Range<usize>> for BoxedSlice<T> {
type Output<'a> = Slice<'a, T>;
fn index<'s>(&'s self, _: Range<usize>) -> Slice<'s, T> { .. }
// Note tha `'s` appears in the output so this operation freezes `self`
} This set of traits can also handle your non-freezing use case. impl<'a, 's> IndexNoHKT<&'s str> for Node<'a> {
type Output<'_> = Option<Node<'a>>;
fn index<'e>(&'e self, _: &'s str) -> Option<Node<'a>> { .. }
} Given that the set of HKT traits is more flexible than the non-HKT one, I wonder if we can add the non-HKT set now and deprecate it later in favor of the HKT one, or somehow just upgrade the non-HKT traits to use HKT in a backward compatible way. |
I'm of two minds about DerefGet/IndexGet. On the one hand, I see the On Wed, Sep 23, 2015 at 1:55 AM, Jorge Aparicio notifications@github.com
|
Seems like this RFC has been hanging around. To be honest I've sort of forgotten the trade-offs, but from what I can see the RFC has been updated. @aturon what do you think, shall we try to move forward with this now? I think one question is whether there are people who are interested in implementing it. It's not a blocker if there are not, of course, but most of the main rustc hackers seem to have their hands full at the moment. |
Have you not noticed the implementation conveniently provided by the author of this RFC? |
I'm in favor - would be most useful for cgmath. Currently you have to do ugly derefs in order to assign using |
On Thu, Nov 05, 2015 at 03:12:10PM -0800, Peter Atashian wrote:
I've noticed it, yes, but last time I checked it needed to be rebased. |
This RFC is entering its week-long Final Comment Period. 💬 |
I'm still very wary of this proposals interaction with placement. I'd rather not have:
as three roughly equivalent alternatives. |
@Florob And of course, that's not counting the It is interesting that, in the same way this RFC special-cases indexing and assignment as a pair, you could imagine special-casing indexing and placement: To me there are two main motivations for this RFC:
I think both of these motivations point to needs that cannot be addressed by placement alone. Personally, I find both motivations reasonably compelling, and am willing to trade that against the "more than one way to do it" with placement (especially if we can get a symmetric placement syntax like My biggest worry about the RFC is the subtle rules regarding when to use |
We already have some troubles selecting between Being a proponent of placement-in, I’d like to wait and see how emplacement works out for this use-case, and if it doesn’t I also do not see how |
I generally like the idea behind this RFC, but I second (third) the concern that this has overlap with placement-in. Given that we already know that we definitely want placement-in regardless, I'd be willing to postpone this until after we've had time to experiment with placement-in and determine if this RFC is still necessary. However, that's working under the assumption that placement-in is coming "sometime soon" (say... six months or less?), which I really really hope is true. |
I infer you must be talking about support for placement-in on the various stdlib types? (See also rust-lang/rust#30172 ) Update: Or are you asking about when the placement-in feature will be stabilized ? |
We discussed this in the @rust-lang/lang meeting yesterday. In general, there are some mixed feelings about the design:
All that said, it seems clear that Overall, this seems like a case where accepting the RFC might allow us to gain the experience we need to reach a final decision. However, even if we had a feature gate, we still couldn't add Even if a feature-gated impl is not used in libstd, though, it might allow experimentation in external libraries. Having convincing (and working) examples of matrix abstractions, or other types that rely on Ultimately, we didn't really reach a final decision, but we plan to discuss a bit more next week. In the meantime, any thoughts on the above comments would be most appreciated. Other notes:
|
+1 to adding the RFC, feature gating, experimenting in libraries. I use Rust for numerics, hence also matrices (currently scirust, also looking at others). I think that full, thoughtful support for convenient slicing, including stuff like
and Multidimensional arrays, dataframes make completely unreasonable demands on this syntax in other language; finding the right tradeoffs for Rust will not happen in a week, maybe even not in a year, but it is important work. |
I'm also on favor of adding this behind a feature gate for library experimentation. I totally see the hesitation in adding this, particularly in the context of HashMap etc but for newer data structures that do not have an already-established api, this could be ergonomic. |
We discussed this RFC in the @rust-lang/lang meeting last night. We've decided to postpone this RFC under Issue #997. The concerns are the same as the ones I documented before. The thought was that it would be good to push on the emplacement syntax and API and see how that plays out before making a firm decision here. One observation that @huonw made which I don't see in my previous post is that a syntax like |
Rendered
Implementation: rust-lang/rust#25628
cc @sfackler @gankro
cc @rust-lang/lang-teamcc @nikomatsakis @aturon @huonw @nrc @pnkfelixcc #997