Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upIndexAssign: overloading the `a[b] = c` expression #1129
Conversation
Gankro
reviewed
May 19, 2015
| map[key] = value; // equivalent to `map.insert(key, value);` | ||
| ``` | ||
|
|
||
| - Setting each element of a "slice" to some value |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Gankro
reviewed
May 19, 2015
|
|
||
| ``` rust | ||
| // Copy the third row of `another_matrix` into the second row of `matrix` | ||
| matrix[1] = &another_matrix[2] |
This comment has been minimized.
This comment has been minimized.
Gankro
May 19, 2015
Contributor
Woah, this is pretty funky. How are you even assigning a reference to something by-value here?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
japaric
May 20, 2015
Author
Member
@Gankro That expression is evaluated as matrix.index_assign(1, &another_matrix[2])
@bluss With IndexMut it would need to store the RHS which has type &Row into a variable with type Row.
(Also in this case Row is defined as Row([T]), ie is unsized, that's another reason why IndexMut won't work: the LHS would be unsized, which is not allowed is an assignment)
This comment has been minimized.
This comment has been minimized.
bluss
May 20, 2015
Aha I see! I'll just write it down so that I can think about it: :)
matrix[1] = &another_matrix[2]
IndexAssign::index_assign(self: &mut [T], index: usize, rhs: &[T])
This comment has been minimized.
This comment has been minimized.
nikomatsakis
May 22, 2015
Contributor
I've not had time to give this a detailed read yet, but it sounds like you're suggesting we'd pick the trait based on some pretty fine-grained criteria. It could work if that turns out to be part of the trait lookup, I guess.
This comment has been minimized.
This comment has been minimized.
|
Clarification request: is this RFC actually proposing we provide |
nrc
added
the
T-lang
label
May 20, 2015
nrc
reviewed
May 20, 2015
| ``` rust | ||
| let mut matrix = { .. }; | ||
| // Set each element of the second row of `matrix` to `1` |
This comment has been minimized.
This comment has been minimized.
nrc
May 20, 2015
Member
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).
This comment has been minimized.
This comment has been minimized.
japaric
May 20, 2015
Author
Member
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.
This comment has been minimized.
This comment has been minimized.
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 comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
I agree with the general idea, but I’d very much prefer |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
|
It does seem a bit footgunny that |
This comment has been minimized.
This comment has been minimized.
|
I'm in favor of this RFC, because I view it as a special case of |
This comment has been minimized.
This comment has been minimized.
|
@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 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
+1 And a small question: does |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
cristicbz
commented
May 26, 2015
|
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. |
This comment has been minimized.
This comment has been minimized.
|
If IndexAssign panics on missing keys, then it's basically useless. The whole point is that it's sugar for insertion. |
This comment has been minimized.
This comment has been minimized.
cristicbz
commented
May 26, 2015
|
@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
|
This comment has been minimized.
This comment has been minimized.
Florob
commented
May 27, 2015
|
Are there any thoughts on how this interacts with placement-new? |
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment has been minimized.
This comment has been minimized.
bluss
commented
May 29, 2015
|
The notation |
This comment has been minimized.
This comment has been minimized.
gsingh93
commented
May 29, 2015
|
@nikomatsakis That is unless the |
This comment has been minimized.
This comment has been minimized.
|
@bluss ah, ok, I see. You're right, I was overlooking that (or missed it). |
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment has been minimized.
This comment has been minimized.
|
I think that seems reasonable to me. |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Jul 8, 2015
|
(Using type ascription syntax to illustrate.) None of the two ways presented to go about
|
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
So I would like to move this RFC to final comment period, but I think it needs to be updated first. |
This comment has been minimized.
This comment has been minimized.
gsingh93
commented
Sep 21, 2015
|
@japaric ping on that update, looking forward to this. |
This comment has been minimized.
This comment has been minimized.
|
My dreams are really for an |
This comment has been minimized.
This comment has been minimized.
|
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 comment has been minimized.
This comment has been minimized.
|
This is totally unrelated to the current RFC, but the use cases I see for |
This comment has been minimized.
This comment has been minimized.
|
@japaric https://github.com/NoLifeDev/nx-rs/blob/master/src/node.rs#L72-L92 |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
|
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
|
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
Have you not noticed the implementation conveniently provided by the author of this RFC? |
This comment has been minimized.
This comment has been minimized.
|
I'm in favor - would be most useful for cgmath. Currently you have to do ugly derefs in order to assign using |
This comment has been minimized.
This comment has been minimized.
|
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 comment has been minimized.
This comment has been minimized.
|
This RFC is entering its week-long Final Comment Period. |
aturon
added
the
final-comment-period
label
Nov 23, 2015
This comment has been minimized.
This comment has been minimized.
Florob
commented
Nov 23, 2015
|
I'm still very wary of this proposals interaction with placement. I'd rather not have:
as three roughly equivalent alternatives. |
This comment has been minimized.
This comment has been minimized.
|
@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 |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
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 ? |
This comment has been minimized.
This comment has been minimized.
|
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:
|
SimonSapin
referenced this pull request
Dec 18, 2015
Closed
Tracking issue for `clone_from_slice` stabilization #27750
This comment has been minimized.
This comment has been minimized.
daniel-vainsencher
commented
Dec 29, 2015
|
+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. |
This comment has been minimized.
This comment has been minimized.
pliniker
commented
Jan 19, 2016
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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 |
japaric commentedMay 19, 2015
Rendered
Implementation: rust-lang/rust#25628
cc @sfackler @Gankro
cc @rust-lang/lang-teamcc @nikomatsakis @aturon @huonw @nrc @pnkfelixcc #997