-
Notifications
You must be signed in to change notification settings - Fork 13k
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
var keyword for mutable locals only #2643
Comments
I have to confess, I at first thought that we should use the same keyword for mutable vars and mutable fields, but |
I think it's a feature that declaring a mutable variable is ever-so-slightly more cumbersome than an immutable one. I can see programmers using just "var" to be "consistent" or because "var" would be more powerful (don't have to change it if you decide to mutate later). Then you end up with less readable code overall. Not suggesting that Rust should be a serious bondage & discipline language, but a gentle nudge in the right direction is morally justifiable, I think (i.e. the rule would be "for safe code, the safer constructs should be less noisy than the more powerful but easier-to-mess-up constructs"). |
On one hand I like this, since it would remove the visual ambiguity from this form:
But I'm inclined to side with ssylvan. Declaring mutables doesn't exactly need to be ugly, but I think it makes sense if they're ever-so-slightly less convenient to create than immutables, if only by a single keystroke. The activating keyword also needs to be distinctive, and (IMO) I still like the idea of replacing |
@pcwalton pointed out a problem with just using
Record literal, or block with local variable? |
I could see a lot of programmers just learning that I overheard someone point out yesterday that now |
I'm somewhat indifferent, but I somewhat prefer |
While I'm still wary of using |
There is a plan to make mutability a part of the type. Does that affect locals and make this irrelevant? |
How about:
Like in Scala. |
I think @brson is right and this issue vanishes once we move Closing this issue for now; reopen if you think I'm wrong! |
I am not sure about this. I like the idea of moving mut into the type, but I don't know that it's a "done deal"---there may be lingering weirdness in there. In any case, I never considered that one might write To do otherwise would seem to imply that if you have an array |
@Dretch I don't love val/var because they are not distinct enough, though the Scala precedent is nice. I share @eholk's concern about people learning to use But I don't h ave a preference and I do appreciate when I can compose functions entirely of statements beginning with three-character keywords. |
@nikomatsakis In particular, it makes sense to me that the rules about single-assignment should come from the mutability of the declaration rather than the type. Subtly changing the assignment rules based on type smells funny to me. I'm inclined to agree with @pcwalton that we shouldn't penalize programmers from using a mutable binding if that's what they want. As for the concern about people unnecessarily using Dave |
Is it really that terrible if programmers declare all their variables mutable? It seems like it's not the end of the world if we have a set of Rust programmers that just think |
IMHO good syntax design is not just about making "everything" you might ever want to do convenient, it's about gently nudging people on to the "smooth path" of the language's semantics and design goals. For example, you probably wouldn't add special syntactic support for linked lists in Rust (a la Haskell), because one of Rust's foundational principles is to be efficient, and pervasive use of linked lists will work contrary to that principle. For the same reason sharing mutable data between threads probably shouldn't be too convenient (since safe concurrency is another principle), nor should it be super convenient to cast an arbitrary int to a pointer (since memory safety is a big principle). Not to say that it should be impossible to do any of these things, mind, just proportionately inconvenient so that it's clear from the syntax which is the idiomatic way to write Rust. Mutable (local) variables aren't nearly as bad as any of these, but if Rust is indeed favouring immutable data for correctness and maintenance reasons (something I personally agree with), then the syntax should ideally give a gentle nudge in that direction. Even a single extra character or an extra modifier sigil or whatever would be enough to make it clear that "let" is less complicated than "let mut" or "let!" or whatever, and therefore must be the preferred default you should try to go for when you don't actually need the variable to be mutable. |
@ssylvan Oh, I understand that point, it's just a question of degree, and the balance of trade-offs. We already promote immutability of data structures, and IMO immutable locals are less important to promote than immutable fields. (Especially since, IINM, we don't allow mutable locals to escape in heap closures.) And the loss of the ability to refactor between Dave |
Well in that case at least "let foo = mut bar" or "let foo := bar" as opposed to "let mut foo = bar" would make the first token line up. Presumably the variable name will be of variable length so it's not so important to avoid extra modifiers on the rest of the statement. |
Oh hey, I'm kinda partial to the Dave |
On second thought, Pascal is permanently uncool. I take it back. :) Dave |
Also,
I've found that pattern useful at times, although it seems like there's probably always another way to write the same pattern. |
@eholk I don't think it prevents that. But I still think it'll look too weird to programmers from almost any mainstream language. Dave |
Regarding
brson's argument for the current syntax (i.e. that the mutable declaration first requires the immutable declaration) is convincing. It's totally great if programming languages are opinionated, just as long as they aren't jerks about it. :) |
Not interested in
The main reason to avoid "accidental" mutable locals is that we introduced environment capture, so they turn into a form of action-at-a-distance, as well as hazards for a variety of analyses like borrowing. (All lets were initially mutable, but we also had no environment capture, only bind. Now we have no bind, only env capture. Tomayto, tomahto.) |
I believe mutables cannot be implicitly captured now. |
@graydon is correct that there were two original motivations. However only one is still relevant. The two motivations were
It turns out that the latter is no longer relevant. The use of mutable/immutable variables was too crude in practice so borrowck has the idea of borrowing a variable "temporarily"---a mutable variable can be borrowed with an immutable ptr so long as the variable is not modified while the pointer is in scope. We could perhaps just remove the idea of mutable/immutable locals and go back to the old rule---everything is mutable. We could then issue warnings when a variable that is implicitly copied into a closure is modified after the closure is created. |
There's a third motivation: immutable variables are easier to reason about. If everything is mutable you have to scan around the whole function to see what values a variable might have during its life time. Every variable potentially has complicated data flow (esp. with loops, branches, mutable function parameters, etc.) and it's hard to see what's going on without carefully analyzing every statement. If you have only one or two mutables in a function it sort of acts to "flag" them so that you're more careful when reading code involving hem. |
@Dretch I also like the Scala style, with "val" and "var" key words. |
I like how the current syntax causes mutables to stick out like a sore thumb; it makes scanning the code easier. |
I understand that mutable fields are going to be removed from rust. Does that mean that |
Also I believe structural records are going, which removes the ambiguity even if mutable fields remain. |
@Dretch it's true that mutable fields are on their way out, and structural records are already gone. I'm mostly indifferent to the issue, although I would like to point out that it might make sense for let foo = 1; // immutable
/* 10,000 lines of code here */
let mut foo = foo; // we're making foo mutable, totally understandable
/* 10,000 lines of code here */
let foo = foo; // potential wtf With the proposal: let foo = 1; // immutable
/* 10,000 lines of code here */
mut foo = foo; // a mutable foo, no problems here
/* 10,000 lines of code here */
let foo = foo; // slightly less of a potential for wtf, since we officially have two declaration forms |
Though I also feel like this would make the Rust-ism "absence of mut implies immutability" less consistent, because we'd still be writing |
Kotlin also uses |
I don't think we're going to make this change, but I'll nominate for milestone 1, well-defined, so we can settle it. |
consensus is to not do this, as it's incompatible with moving mut to pattern bindings. closing. |
I've just come across this bit of code...
and this is the first time I've come across var in rust. So the above code could be re-written as:
, correct? Thanks all just looking for clarification. |
@Jeklah I'm curious, where did you come across this code? Any Rust code using |
It was in a wgpu tutorial. I was thinking I think id prefer to use let mut instead of var just for uniformity and less of people asking "what's var for when we have let mut?" Makes more sense var is an old thing. Thanks for the heads up. |
The code you posted isn't Rust code at all, it's wgsl code, which is a completely different language with different syntax and behavior. |
Interesting as I'm running it with cargo. |
I assume you're using the Even though Rust macros are able to include non-Rust code, such as typed-html including HTML code, or include-sql including SQL code. |
That is correct. I'm following a tutorial on using rust with wgsl. |
`goto-synthesizer` should take the same backend options as `cbmc` to make sure that the checker we used to check loop-contracts candidates is the same as the checker we verify the final goto-binary.
Issue #1273 proposed
let mut
for mutable locals andmut
for mutable fields.let mut
is more verbose than a single keyword and also breaks column alignment. People rightly didn't like the idea ofvar
for mutable field declarations. But I think nobody suggested the idea of usingvar
for mutable local declarations andmut
for mutable field declarations:Dave
The text was updated successfully, but these errors were encountered: