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 upLanguage ergonomic/learnability improvements #17
Comments
aturon
added
Project
T-compiler
T-lang
labels
Jan 31, 2017
This was referenced Jan 31, 2017
This comment has been minimized.
This comment has been minimized.
|
Update: added the trait aliases RFC. |
This comment has been minimized.
This comment has been minimized.
|
Update: added Extending |
This comment has been minimized.
This comment has been minimized.
|
Update: added Delegation of impls |
This comment has been minimized.
This comment has been minimized.
|
Update: added Add |
This comment has been minimized.
This comment has been minimized.
RUSshy
commented
Feb 6, 2017
|
Please add |
This comment has been minimized.
This comment has been minimized.
Ixrec
commented
Feb 7, 2017
|
@RUSshy Could you be more specific about what "adding class" means to you? Most languages with "classes" have dozens of distinguishable features associated with their classes, and Rust already has analogues for many of them. |
This comment has been minimized.
This comment has been minimized.
RUSshy
commented
Feb 7, 2017
•
pub trait Drawable
{
fn draw(&self);
}
pub trait Updatable
{
fn update(&self);
}
pub struct Entity
{
pub id: i32,
pub x: f64,
pub y: f64,
pub z: f64
}
impl Entity
{
pub fn new(id: i32) -> Self
{
Entity{id: id, x: 0.0, y: 0.0, z:0.0}
}
}
impl Drawable for Entity
{
fn draw(&self)
{
println!("Draw: {}", self.id)
}
}
impl Updatable for Entity
{
fn update(&self)
{
println!("Update: {}", self.id)
}
}to this: pub class Entity : Drawable, Updatable
{
pub id: i32;
pub x: f64;
pub y: f64;
pub z: f64;
pub fn new(id: i32) -> Self
{
Entity{id: id, x: 0.0, y: 0.0, z:0.0}
}
fn update(&self)
{
println!("Update: {}", self.id)
}
fn draw(&self)
{
println!("Draw: {}", self.id)
}
}I love rust, i find it modern and really nice to use, but i think having class to merge struct and impl can help something with readability, because i find myself repeating and write duplicate code |
This comment has been minimized.
This comment has been minimized.
bestouff
commented
Feb 7, 2017
|
@RUSshy why wouldn't this work: pub struct Entity : Drawable, Updatable
{
...
}? (Otherwise to me, the two most useful items are the ones in "Early stage thoughts", i.e. non-lexical lifetimes and module system improvements) |
This comment has been minimized.
This comment has been minimized.
Nemikolh
commented
Feb 7, 2017
•
|
@RUSshy It would give wrong impression to beginners in my opinion. One could believe that all the trait being implemented by a type would appear next to the class definition itself. But this is obviously not true (see Besides how would you deal with Would the code really be more readable at this point? It seems, that you would definitely end up splitting your class into multiple impls as your code evolves. |
This comment has been minimized.
This comment has been minimized.
Ixrec
commented
Feb 7, 2017
I don't see any duplicate/repeated code in your example, just three impl blocks merged into the struct definition. I do see the appeal of that sugar unifying "obviously related" blocks of code, but it is just sugar, and it doesn't appear to save very much typing or confusion compared to some of the other proposed sugars such as delegation, and with that particular keyword there's definitely a risk of misleading novices. I agree with Nemikolh that experimenting with a "class macro" would make more sense for now. Though we should probably move this discussion to https://users.rust-lang.org/ or https://internals.rust-lang.org/ since it's at most a very tiny piece of the puzzle this issue is about. |
This comment has been minimized.
This comment has been minimized.
withoutboats
commented
Feb 7, 2017
|
My impression is that thread is for a high-level coordination of the work toward this roadmap goal. Brainstorming specific language feature ideas should be at either https://internals.rust-lang.org or an issue on the RFC repo https://github.com/rust-lang/rfcs/issues |
This comment has been minimized.
This comment has been minimized.
|
Update: adding reference to this thread on internals which discusses some additional ideas. |
This comment has been minimized.
This comment has been minimized.
|
Update: added match ownership ergonomics. |
This comment has been minimized.
This comment has been minimized.
|
One idea that would make working with capn proto and similar systems so so much nicer would be something like attributes as exist in C# or Python, where one can use field access syntax but underneath call functions to get/set the field. The current state of the art in Rust is explicit getters and setters, which leads to terrible ergonomics for code interacting with data at the edges of the process boundary, to the point of Java-level verbosity. In the past (pre-1.0) I know there was some discussion and rejection of this, but I'd like to bring it up again. |
This comment has been minimized.
This comment has been minimized.
|
Updated with a link to the new blog post and several in-progress RFCs. If there are pre-RFC internals threads that should be cited, please leave comments and I'll add them! |
This comment has been minimized.
This comment has been minimized.
F001
commented
Mar 4, 2017
|
The "Delegation of impls" and "Delegation of implementation" both point to rust-lang/rfcs#1806. They are duplicate. |
This comment has been minimized.
This comment has been minimized.
crumblingstatue
commented
Mar 4, 2017
|
I see default struct field values is listed here. Are there any learnability improvements that it provides, or are the benefits purely ergonomic? In the latter case, I find it odd that it would be tracked here. There are lots of ergonomic improvements (e.g. default/keyword args) that are currently postponed, and we couldn't possibly fit them all into this year's roadmap. |
This comment has been minimized.
This comment has been minimized.
|
@crumblingstatue I went through the open lang RFCs looking for any that touched on ergonomics, just to have them tracked in a central place. I'm open to keeping this tracking issue more focused, but I'm not sure what the best "cutoff" line should be. |
This comment has been minimized.
This comment has been minimized.
LegNeato
commented
Mar 7, 2017
|
What's the process for nominating an RFC for this? Sorry if I missed it. As a Rust n00b I'd like to nominate rust-lang/rfcs#1078 |
This comment has been minimized.
This comment has been minimized.
withoutboats
commented
Mar 7, 2017
|
That issue has an RFC which will probably be merged soon :-) rust-lang/rfcs#1869 |
This comment has been minimized.
This comment has been minimized.
hgrecco
commented
Mar 9, 2017
|
I find this example from the book quite annoying: enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x: x, y: y } => move_cursor(x, y),
Message::Write(s) => println!("{}", s),
};
}If you are matching an Enum variant, cannot
I have seen ways to mitigate this (such as use |
This comment has been minimized.
This comment has been minimized.
|
Please file bugs on the Rust or rfcs repo, this is for tracking efforts to improve readability and not discussing the specifics themselves. (In that specific case, it used to be the opposite, actually, but then everyone namespaced enums as |
This comment has been minimized.
This comment has been minimized.
|
@Manishearth @hgrecco to clarify, I'd actually recommend opening threads on https://internals.rust-lang.org/ with ideas, and then posting a link here. I am using the comment thread/headers to track ideas floating around. |
This comment has been minimized.
This comment has been minimized.
This brushes on a very related issue with trait usability. We have a lot of "drill down" traits, like Eq, Serialize, Hash, etc. Most implementations are a I'm not really proposing a proper solution here, just mentioning that these traits have a class of problems associated with them. The class of problems comes from the fact that these traits are usually structurally-derived but sometimes need manual impls, and currently the structural-derive needs explicit opt in (which makes sense, really). Throwing a half solution into the mix: in the past we have discussed things like deferred derive where This "solution" if used too much would have codesize bloat problems, and there's also the whole interaction with safety (you don't want someone to force-derive on an unsafe abstraction), but it's something that can be built upon. |
This comment has been minimized.
This comment has been minimized.
djc
commented
Apr 16, 2017
|
It seems like @Manishearth's comment is really concerned with what I call deriving-at-a-distance. However, if |
This comment has been minimized.
This comment has been minimized.
Well, you have coherence problems there. Unless you're the one defining the deriving stuff. Crates like serde/heapsize may have to do manual tinkering to implement these traits since they themselves can't apply the deriving syntax to things from std. My solution to the drill down issue was to ignore the part of generating impls at a distance, and just make the codegen accessible. Impls come with a whole host of other problems (coherence) Anyway, this is kind of off topic I guess. |
This comment has been minimized.
This comment has been minimized.
|
@Manishearth Crate introspection is possible after loading their metadata, so perhaps a feature along the lines of |
This comment has been minimized.
This comment has been minimized.
|
Yep. We have discussed this before, I think I understand that it's feasible, it's just designing the exact API (and figuring out if we actually need it) that needs doing. |
This comment has been minimized.
This comment has been minimized.
burdges
commented
Apr 16, 2017
|
Is there any problem with using specialization to reduce the boilerplate around
I suppose |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
commented
Apr 19, 2017
Can you clarify what you envision this syntax as doing? It seems to me that the interesting (and hard) problem here is deciding what to do about coherence. Ah, would this be something we would do in the crate that defines |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis Yupp, giving the derives an approximation of the original AST, from crate metadata. |
This comment has been minimized.
This comment has been minimized.
|
Is there a more detailed location to add thoughts about "Allow owned values where references are expected" ? |
This comment has been minimized.
This comment has been minimized.
|
@shepmaster There's not currently, but you're welcome to make an internals thread on the topic (and I'll link it here)! FWIW, the strawman proposal is to automatically coerce via We already use this pattern in std, but it'd be nice to have it apply uniformly and not have to muck up signatures with it. |
This comment has been minimized.
This comment has been minimized.
|
Added:
|
This comment has been minimized.
This comment has been minimized.
@aturon I've created a thread as requested. We'll see where it goes ;-) |
This comment has been minimized.
This comment has been minimized.
|
Updated to add some ideas around coercions, e.g. https://internals.rust-lang.org/t/ergonomics-initiative-discussion-allowing-owned-values-where-references-are-expected/5161/22?u=aturon |
aturon
self-assigned this
Jun 7, 2017
This comment has been minimized.
This comment has been minimized.
|
Updated with the latest status info. |
This comment has been minimized.
This comment has been minimized.
le-jzr
commented
Jun 9, 2017
|
Any news regarding It would also solve the weirdness where current bound |
This comment has been minimized.
This comment has been minimized.
|
@le-jzr I'd love to have automatic implementations like that - it'd also be possible to implement |
This comment has been minimized.
This comment has been minimized.
glaebhoerl
commented
Jun 12, 2017
|
I think this RFC ("Allow comparisons between integers of different types") is also relevant here. Much like default binding modes for |
This comment has been minimized.
This comment has been minimized.
suhr
commented
Jun 23, 2017
|
Local Long story short, I want to be able to write something like this: trait Foo {
use std::iter::IntoIterator;
// ...
} |
This comment has been minimized.
This comment has been minimized.
crumblingstatue
commented
Jun 23, 2017
|
@suhr: That's rust-lang/rfcs#1976, and it's about to get postponed. |
This comment has been minimized.
This comment has been minimized.
burdges
commented
Jun 23, 2017
•
|
It turned out trickier than folks thought. I think you can mostly work around it using submodules judiciously.
|
This comment has been minimized.
This comment has been minimized.
suhr
commented
Jun 23, 2017
Well, that's unfortunate.
It's an ugly and awkward kludge that is not worth it. |
This comment has been minimized.
This comment has been minimized.
dobkeratops
commented
Jul 25, 2017
•
|
I wonder if this would get a different reaction in the context of this thread. alternating between languages, I continue to find the need to micromanage traits to be irritating (i.e. the single function trait case), but strangely in haskell the typeclasses don't feel as bad. It's because the there, defining and referring to the 'type class' saves you writing details out again. Initially I found it odd, but their function signatures being split are actually clearer. Hence this PR. People are complaining 'you read it more than you write it' but it's the repetition that is annoying: if I'm specifying the types , I would rather it figures out the trait from them. If I've specified the trait, it makes sense to use that to infer the types. Users are going to read the trait declaration itself more surely, which has all the types, and you need to refer back to that to implement anyway, surely. Aren't you just taking up more screenspace in a useless way displaying it again. The trait defs are very easy to grep for ( i have that all working nicely in emacs), and there's rustdoc too. Something else to mention is this mental flip of arguments in the single-function-trait case (e.g. used for overloading).. I wish you could write the impl the other way round so that it's
wouldn't that be so much bettter? the mental flip between the intent "LHS,add,RHS" and expressing the trait makes the trait so much more annoying. Again the 'multi-parameter-typeclass' case in haskell is more pleasant, possibly because you get to choose the order, so in the case of 'a single function class' you can write the class-types in the same order as the function types. (there's extra symmetry from the fact they have no 'self', but with better ordering I don't think special-Self would be a pain) Combined with eliding the signature types, that might be enough for me to achieve peace with this system. |
This comment has been minimized.
This comment has been minimized.
burdges
commented
Jul 25, 2017
•
|
I believe mutability, references, lifetimes, etc. change that calculation somewhat from Haskell, so maybe wait until folks become more comfortable with lifetime elision for At least one can then deduce if type elision ever confuses the reader familiar with lifetime elision. If so, type elision could be restricted to cases where lifetime elision works. And maybe it should be restricted to not doing |
This comment has been minimized.
This comment has been minimized.
dobkeratops
commented
Jul 26, 2017
•
|
most of the time operators are just reference inputs, and the lifetime elision kicks in;
So basically the times you actually need to write lifetimes, you're doing something rarer (IMO). Eliding information in the obvious cases will give you more 'cognitive budget' to spend on the unusual. Also the information is still there and will surface if you hit compile. I argue people reading code are more likely to be reading the trait, which does have the full types. also I argue haskell's split is actually helping readability, regardless of how much type information there is Conversely if I must write out the types then I'd prefer it to do the opposite: figure out the trait from the types. This reminds me of years of people in C++ claiming "writing out the iterator types is good for you..", delaying the deployment of 'range based for', 'auto' .. |
aturon commentedJan 31, 2017
•
edited by scottmcm
Point of contact
@nikomatsakis @aturon @withoutboats
Overview
As part of the effort to lower Rust's learning curve, we are interested in pursuing a number of language improvements that will make Rust both nicer to use and easier to learn. The goal is to enhance productivity without sacrificing Rust's other core values. See the README for more details.
A kind of manifesto for this work was written up on the main blog.
Status
There are a lot of ideas in flight! The lang team has been focused on writing RFCs for the biggest changes; there are lots of opportunities to help either there, or with more narrow RFCs. If you are interested in the ideas listed below, please contact @aturon or others on the team to hook you up with a mentor for RFC writing!
The potential improvements are organized by broad areas of Rust:
Ownership/borrowing
RFCs
Sketches
AsRefcoercions) (@aturon)Copytypes (@aturon)Traits
RFCs
impl Traitstabilization and expansion (@aturon)impl Traitwork, e.g.impl Traitin traits (@aturon, @cramertj, @eddyb, @withoutboats)T: SomeTraitSketches
dyn Traitsyntax for trait objects (@nikomatsakis, @aturon)Module and privacy system
Landed
pub(restricted)is stable!RFCs
extern crateto take a list (@withoutboats)Sketches
Error handling
RFCs
?to work with more types (@nikomatsakis)?inmain(@nikomatsakis)Resultwhen leaving a block (@scottmcm, @nikomatsakis, @aturon)Try<Ok=()>: rust-lang/rfcs#2120Primitive types/core traits
Sketches
String(@aturon)PartialEq/PartialOrd(@aturon)#[derive(Data)]Type annotations/verbosity
RFCs
const/staticdeclarations (@schuster)Sketches
matcharms::infoo::<u32>(blah), in at least the single-argument caseFFI
Landed
Other
RFCs
async/awaitnotation built on top; we are considering landing that experimentally in the compiler.More ideas
returnand closuresIdeas that didn't make it
else match