-
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
Extend format_args implicit arguments to allow field access #3626
base: master
Are you sure you want to change the base?
Extend format_args implicit arguments to allow field access #3626
Conversation
Why wasn't this in the original RFC? Were there concerns or was it just a case of being cautiously minimalistic? |
@ChrisDenton Yes. See https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html#alternative-solution---interpolation and also the Future Possibilities section of 2795. |
does there need to be a discussion about the reaction to |
Thanks! Maybe I'm missing something but there doesn't appear to be any discussion on that in this RFC? I only see a terse reference to it in the disadvantages section? Also there's no mention of the exploration of alternative syntax mentioned in rfc2795's Future Possibilities. Even if that's not being considered in this RFC, it would be nice to at least acknowledge that. |
I think allowing |
One property that current format strings have is that nothing in the format string can typically have side effects (other than a strange |
Also of the opinion that With Or, if we decide against that, I would strongly recommend just making the evaluation order explicitly linear, with |
this is exactly the same as accessing interior mutability in
it can't panic actually, it is only a call to
there are ways around that ( |
I just found out that #[derive(Debug)]
struct Await {
r#await: u32,
}
fn main() {
let r#await = Await { r#await: 6 };
assert_eq!(format!("{await:?}"), "Await { await: 6 }".to_string()); // <-- currently compiles!
// assert_eq!(format!("{r#await:?}"), "Await { await: 6 }".to_string()); // <-- error, see #115466
assert_eq!(format!("{await.await}"), "6".to_string()); // ?
assert_eq!(format!("{await.r#await}"), "6".to_string()); // ??
assert_eq!(format!("{r#await.r#await}"), "6".to_string()); // ???
} |
The rationale for limiting expression types in format strings isn't to limit side effects, it's purely a matter of syntax, and what syntaxes create confusion within a format string. On that basis, allowing anything that uses If we ever added arbitrary expressions in the future, we'd want some kind of delimiter (e.g. a required set of braces or parentheses). I don't know that we want to do that, but I think that'd be a minimum requirement if we did. The rationale for this RFC is that we can add expressions that use |
The problem is that this encourages restricting features added to the language to a particular kind of syntax, or adding custom syntax to support certain operations. If await is accessible just as a field, why can't we add in property functions without parentheses like Python or Kotlin? Why are tuples allowed to treat number indices as fields but not arrays? etc. If the dot access is simple enough, why aren't method calls with no arguments simple enough? etc. It just feels like opening the door to specific kinds of syntax that "feel" okay adds a bad incentive to make syntax "simpler," at the potential cost of clarity. |
Yeah as I've mentioned in #2795 perhaps it's better to go all-in supporting BTW #2795's Future possibilities section also suggested using
Using |
I like One concern I'd have with fully supporting println!("Hello {(match self.pref(person) {
Pref::Like => "friend",
Pref::Neutral => "there",
Pref::Dislike => "you piece of trash"
})}!"); And of course, there could be some confusion with Another way would also be to permit spaces around the formatting string itself within the braces, which feels like it'd be reasonable to have: println!("{greeting} { (person.await) }!") And we could also make this the default for rustfmt when any expression is used inside the braces. This feels ideal since I'm certain that people would like to be able to use |
Unless Rust added something like JavaScript's template strings (which is probably the best way to get something like this to work), the quotes inside the format string need additional escaping. |
Right, you'd probably want to use raw strings here instead, which sidesteps the issue. Although it feels like the parser should be able to recover here and suggest that. |
Wearing my "just another Rust user" hat, this RFC would be nice!
…On Thu, May 9, 2024, at 1:09 AM, Clar Fon wrote:
>> println!("Hello {(match self.pref(person) {
>> Pref::Like => "friend",
>> Pref::Neutral => "there",
>> Pref::Dislike => "you piece of trash"
>> })}!");
> Unless Rust added something like JavaScript's template strings (which is probably the best way to get something like this to work), the quotes inside the format string need additional escaping.
>
Right, you'd probably want to use raw strings here instead, which sidesteps the issue. Although it feels like the parser should be able to recover here and suggest that.
—
Reply to this email directly, view it on GitHub <#3626 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABF4ZQYAXOHR3E5BEECDC3ZBKWEFAVCNFSM6AAAAABHIYOV4KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMBRGY2DEMZTGA>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
A very common thing I do is formatting |
That's exactly the use case that motivated me to write this in the first place. :) |
argument capture: | ||
|
||
```rust | ||
println!("{self.value:self.width$.self.precision$}"); |
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.
What does this mean?
Not sure how it follows from the rest of the RFC.
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.
println!("{0:1$.2$}", self.value, self.width, self.precision);
follows trivially from the definition of argument
in the fmt grammar
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.
Hmm, I have never seen the name$
syntax before, but apparently it's not even a new feature, works since 1.0.
FWIW I use formatting frequently to print the length of lists or do some internal formatting, and it'd be nice to support simple method calls print!("{list.len()}"
print!("{date.utc()}" Not sure how that would interact with the RFC but I'd get way more mileage out of that than just field access. Raw exprs would be ideal of course. This particular method suggestion starts to get hairy when you have arguments to those method calls since those are technically exprs. Not sure how to resolve it without having some weird inconsistency in what can and can't be formatted. print!("{date.utc(arg)}" |
FWIW, in stable Rust I destructure format!("{} jumps over {}", self.source, self.target);
// Current Rust
let Self { source, target } = self;
format!("{source} jumps over {target}");
// Alternate stable version
format!("{source} jumps over {target}", source = self.source, target = self.target);
// RFC proposed
format!("{self.source} jumps over {self.target}"); |
I do not wish to prevent this RFC from moving forward, but I'd also like this as a next step. A common case for me is printing #[snafu(display("Could not delete the crate file {}", path.display()))] |
This RFC extends the "implicit named arguments" mechanism to allow accessing
field names with
var.field
syntax:format!("{self.x} {var.another_field}")
.Rendered