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 upPlace left arrow syntax (`place <- expr`) #1228
Conversation
pnkfelix
added some commits
Jul 28, 2015
pnkfelix
changed the title
Place left arrow syntax
Place left arrow syntax (`place <- expr`)
Jul 28, 2015
This comment has been minimized.
This comment has been minimized.
|
“Lets add Expanding: |
nrc
added
the
T-lang
label
Jul 28, 2015
nrc
assigned
pnkfelix
Jul 28, 2015
This comment has been minimized.
This comment has been minimized.
|
I didn't follow the original syntax debate closely, but I agree with @nagisa that |
This comment has been minimized.
This comment has been minimized.
|
(BTW I don't know if this is clear from this RFC, but the intention is that we will keep the In other words, my intention is that people would not write The place where |
This comment has been minimized.
This comment has been minimized.
|
(but also I don't actually see what the problem is with |
This comment has been minimized.
This comment has been minimized.
|
Another alternative that perhaps I should have listed in the alternatives section
(man and I just thought this was going to be a slam dunk so there would be no need. ;) |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@seanmonstar But as @pnkfelix is trying to clarify, you would use |
This comment has been minimized.
This comment has been minimized.
|
Yay! @nagisa @aturon For example, emplacement into
or emplacement into
Ideally, a couple of basic containers ( Edit: |
This comment has been minimized.
This comment has been minimized.
|
I’ve been convinced. I can’t think up anything better; |
This comment has been minimized.
This comment has been minimized.
|
Thanks @petrochenkov; usage in those examples hews much closer to my intuitions about |
pnkfelix
added some commits
Jul 28, 2015
This comment has been minimized.
This comment has been minimized.
|
@eddyb yea, and I don't necessarily find that better. let x: Rc<i32> = box 5;
// or
let x = Rc::new(5); |
This comment has been minimized.
This comment has been minimized.
|
@seanmonstar In my experience the box would almost always be inferred -- but that also has issues, perhaps (akin to just invoking |
This comment has been minimized.
This comment has been minimized.
|
(I don't think PLACE evaluating before EXPR is a big violator to any explicit rules. Or I don't mind that.) |
This comment has been minimized.
This comment has been minimized.
|
@liigo it was mentioned in previous discussion EXPR might often get quite big, e.g.
which is quite a lot of scanning required to even notice this is not a regular That is, it is preferable to have |
This comment has been minimized.
This comment has been minimized.
|
while |
This comment has been minimized.
This comment has been minimized.
|
I had another look at @petrochenkov's examples, and I believe the following could be made to work: let map = HashMap::new();
map.entry(k) <- vMaybe |
This comment has been minimized.
This comment has been minimized.
|
@eddyb if we’re speaking concrete examples,
|
This comment has been minimized.
This comment has been minimized.
|
@petrochenkov asked:
Yes, now that rust-lang/rust#27215 has landed, the standard library should be able to experiment with adding implementations of the placement protocol to allow use of the |
This comment has been minimized.
This comment has been minimized.
|
@petrochenkov For what it's worth, I've gotten placement working with my tree map library here: https://github.com/apasel422/bst/tree/place. |
petrochenkov
reviewed
Jul 30, 2015
|
|
||
| ```rust | ||
| let ref_1 = arena <- value_expression; | ||
| let ref_2 = arena <- value_expression; |
This comment has been minimized.
This comment has been minimized.
petrochenkov
Jul 30, 2015
Contributor
Maybe in {}/<- should do autoref? Otherwise these nicely looking statements would consume the arena (twice!)
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 30, 2015
Member
You generally don't keep an owned arena around, i.e. arena would most likely have the type &Arena.
This comment has been minimized.
This comment has been minimized.
petrochenkov
Jul 30, 2015
Contributor
You generally don't keep an owned arena around
The same can't be said about vectors. I.e. the v <- elem syntax proposed by @nagisa would have to roll back to v.back() <- elem (or &mut v <- elem). It's not especially terrible, though.
This comment has been minimized.
This comment has been minimized.
nagisa
Jul 30, 2015
Contributor
Alternative I’ve been having in mind here is to change Placer::make_place to take &mut self instead of self.
This comment has been minimized.
This comment has been minimized.
P1start
Jul 31, 2015
Contributor
@nagisa That wouldn’t really work for all cases, because, e.g., [Typed]Arena::alloc takes &self, not &mut self, meaning that you’d be forced to use mutable references when you shouldn’t have to.
This comment has been minimized.
This comment has been minimized.
pnkfelix
Jul 31, 2015
Author
Member
It might end up being moot for Arenas. Namely, We might be able to do
impl<'a> Placer for &'a Arena { ... }
Which in that particular case side steps the choice of self vs &mut self.
I am personally becoming more convinced that it should be &mut self. I spent a while last night looking through my notes to see why I had picked self but did not find a motivating example.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Just to be clear, is it accurate to say that the only reason we want these special placement APIs and operators, instead of moving in the direction of the otherwise simpler and more general |
This comment has been minimized.
This comment has been minimized.
|
@glaebhoerl the phrase "recover from panics" is a bit ambiguous. We do want to be able to continue to properly unwind the stack, but I don't call that "recovery." (My personal take on it is that the Placer protocol is a simpler change than trying to add |
This comment has been minimized.
This comment has been minimized.
|
@glaebhoerl I agree with essentially your entire comment, except that I am slightly less sure about I wonder, for example, whether we can address the current overhead of buffer zeroing in |
This comment has been minimized.
This comment has been minimized.
Hmm... could you perhaps elaborate further on this idea? (Are there analogous owned/dynamic counterparts to the other lifetime-constrained reference types? Can you have first-class places while accomodating both unwinding and One of the reasons for my uncertainty is indeed that while
I had assumed this would be a natural use case for |
This comment has been minimized.
This comment has been minimized.
|
The placement protocol is indeed a version of |
This comment has been minimized.
This comment has been minimized.
|
I noticed this RFC does not specify precedence nor associativity of the operator. As far as associativity goes, it should be right-associative (i..e Precedence is less clear. It should bind stronger than assignment ( |
This comment has been minimized.
This comment has been minimized.
|
@nagisa |
nagisa
referenced this pull request
Oct 13, 2015
Merged
Amend RFC1228 with operator fixity and precedence #1319
This comment has been minimized.
This comment has been minimized.
Just to advertise this at the (hopefully appropriate) audience; here is the current draft, which I plan to update as feedback comes in:
|
This comment has been minimized.
This comment has been minimized.
|
Hmm, am I totally off-base with this comment: https://internals.rust-lang.org/t/placement-nwbi-faq-new-box-in-left-arrow/2789/19? |
This comment has been minimized.
This comment has been minimized.
|
@vadimcn |
This comment has been minimized.
This comment has been minimized.
|
@eddyb: yes, but what I am saying is that in order to use |
This comment has been minimized.
This comment has been minimized.
fenduru
commented
Mar 1, 2016
|
@vadimcn |
This comment has been minimized.
This comment has been minimized.
|
@vadimcn Maybe a clearer example would be: let mut v = vec![];
for x in a {
v.push(box {
if x == 0 { break; }
x + 1
});
}Were The |
This comment has been minimized.
This comment has been minimized.
|
Folks, I totally get what you are saying about the control flow. But look at it from the other side: the raison d'etre of the placement operator is to eliminate temporaries in the process of moving the value into its place. And it does not work for this purpose in cases when the value creator returns anything but the value itself (such as As for the second @eddyb`s motivating example, I find it unconvincing: you can easily re-write it as: let mut v = vec![];
for x in a {
if x == 0 { break; }
v.emplace(|| x+1);
}There may still be useful control flows that work with |
This comment has been minimized.
This comment has been minimized.
|
@vadimcn I would certainly love to just rely on closures. It's also plausible that this is indeed the best path. And maybe if we played enough tricks we might even be able to make All that said, I think there are two points being lost here:
vec <- Entry {
field1: foo?,
field2: bar?,
field3: [0; 1024]
};Something like that might still make sense, it seems to me. You could also imagine things like: vec <- if some_condition {
return;
} else if some_other_condition {
break;
} else {
generate_big_result(some_fallible_thing()?)
};(which I guess is just sort of a variation on a theme). |
This comment has been minimized.
This comment has been minimized.
I agree, this is what we should do.
Since computation of let field1 = foo?;
let field2 = bar?;
vec.emplace(|| Entry {
field1: field1,
field2: field2,
field3: [0; 1024]
});Same applies to the last example. |
This comment has been minimized.
This comment has been minimized.
|
I think the major cost of syntactic support for emplacement, really the major cost for emplacement in general, is pedagogical. Everyone has to learn what emplacement is and when they need to use it. As a rule, additional syntax tends to increase the learning burden, but I think this is an exception. it seems easier to understand the notion of emplacement by dedicating syntax to it than it would be to understand why in some cases you should use a higher order function instead of the more at-hand function. Put another way, I don't think it is easier to explain to new users why they should not use I think it also makes it easier to comprehend when scanning code, because higher order functions can have many different purposes. |
This comment has been minimized.
This comment has been minimized.
|
If Rust decides do add do-notation for Monads (HKTs required), will this RFC have made the do-notation syntax that haskell uses impossible for Rust? Or is it still perhaps possible to give a different context based meaning to |
This comment has been minimized.
This comment has been minimized.
|
@Centril Rust is not a Haskell and it doesn’t face the same constraints as Haskell does/did. We might be considering HKTs for Rust, but Monads and sugar around them has little purpose even with HKTs in play. |
This comment has been minimized.
This comment has been minimized.
|
@nagisa, no that's simply not true. While they have less importance in Rust (due to e.g. sideffects), they're still very useful for e.g. error handling. |
This comment has been minimized.
This comment has been minimized.
|
@nagisa Having a Monad HKT trait allows you to define common operations for a whole host of data structures once. There are already a bunch of Monads in Rust, they are just not grouped together under a trait... Vec, Option, Result, BinaryHeap. Monads are not just a way to get "side-effects", but to redefine the meaning of Other interesting monads: Parsers, Futures, Language-based-security (http://www.cse.chalmers.se/edu/course/TDA342_Advanced_Functional_Programming/lecture9.html). Add to this: Monad transformers, where you have a stack of monads... http://www.cse.chalmers.se/edu/course/TDA342_Advanced_Functional_Programming/lecture6.html Also: monad comprehensions are even more powerful than list-comprehensions. |
This comment has been minimized.
This comment has been minimized.
|
@Centril In a systems language, fancier functional tricks meet the real world and tend to fall apart. As an example, If devirtualization doesn't occur, the slowdown compared to our current iterators or future hypothetical state-machine-based generators can be more than an order of magnitude. Parsers and futures also tend to use implicit existentials and/or GADTs, which admittedly Rust needs, but still have the overhead of boxing and virtual dispatch. We get it, monads are cool. But unless you can find a formalism for "do notation" which allows pervasive static dispatch and no boxing by default instead of as an optimization (and maybe actually integrate it with imperative control-flow primitives), I'm afraid there will always be more specialized solutions, not unlike the theoretical purity of linked lists contrasted with the real-world cache-efficiency of arrays. |
This comment has been minimized.
This comment has been minimized.
|
@eddyb Good comment. Didn't realize that F becomes a virtual call. But just to be clear, you're not saying that Monad::bind itself becomes virtual? Rust is a systems language, but not just. It can be used for other things =) |
This comment has been minimized.
This comment has been minimized.
|
@Centril Indeed, you can have |
pnkfelix commentedJul 28, 2015
Summary
Rather than trying to find a clever syntax for placement-new that leverages
the
inkeyword, instead use the syntaxPLACE_EXPR <- VALUE_EXPR.This takes advantage of the fact that
<-was reserved as a token viahistorical accident (that for once worked out in our favor).
rendered draft.