-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: Go 2: Printf unspecific string interpolation evaluating to string and list of expressions #54588
Comments
I don't understand the need for the "New" methods, you can do this:
|
This is not necessary, it will make the programming style confusing and will increase the complexity of understanding the program |
@au-phiware For this proposal we need a different function, since |
I disagree that this proposal is a duplicate of #50554 because this proposal is incompatible with |
@Cookie04DE I don't think it helps us to have multiple different discussions about approaches to string interpolation. That's hard to follow and hard to remember all the places to look. I think it's more useful to have a single issue that discusses different approaches in the hopes of building consensus. Thanks. |
This proposal is meant to be an alternative for, not a replacement of #50554.
#50554 attempts to find a mechanism that integrates directly into
Printf
style functions. This proposal aims for a broader scope which breaks this compatibility but provides greater value overall. It also tries to integrate the previous discussion and suggested improvements.Like #50554 it tries to maintain the separation between the spec and the standard library.
Note that this necessitates the use of different functions. Since I don't have a good name for them yet, I just add
New
to their name. Sofmt.Printf
becomesfmt.PrintNewf
andlog.Fatalf
becomeslog.FatalNewf
. That's just for demonstration purposes though and these need better names.Author background
Experienced.
Java, Kotlin, Rust, C
Related proposals
proposal: Go 2: string interpolation #34174 attempts to provide string interpolation at the language level (the specific formatting of each type will be recorded in the language spec)
proposal: Go 2: string interpolation evaluating to string and list of expressions #50554 attempts to provide a feature directly compatible with
Printf
style functions to aid in readability.Unlike proposal: Go 2: string interpolation #34174 this proposal does not specify the formatting of each type and lets the user decide (even applications other than string formatting are possible; more on that later).
Unlike proposal: Go 2: string interpolation evaluating to string and list of expressions #50554 the language level functionality is not directly compatible with
Printf
style functions but aims to provide a broader, more useful functionality.No.
No.
Proposal
Please refer to the section after next.
Traditional C style format strings are easy, robust and well known, but they suffer from one main problem: It is hard to read and modify them.
Consider the following:
Did you catch that
buyURL
andstockCount
were accidentally swapped?It is also difficult to modify it correctly. If you want to change the position of an expression you need to move the formatting verb (
%v
for example) and the expression in the list so the order is correct again. Or if you want to delete an expression you need to delete the marker in the string and find the correct expression in the list and delete that too.The problem becomes worse the bigger the format string.
This is how the (corrected) example would look like with the new syntax:
The proposed changes could also be used for other purposes.
Example using current syntax:
This could be rewritten into this:
I propose to add the following builtin type:
Furthermore I propose to add two types of literals. I will refer to them as "format string" (fs for short) and "raw format string" (rfs for short) henceforth.
An fs has the following form:
It behaves very similar to string literals with the exception that it has to be prefixed with
%
and may contain Go expressions contained within curly brackets ({
and}
).The brackets have to match up, so there may be no closed curly brackets without corresponding opening brackets and the other way around.
If a literal open curly bracket or a closed curly bracket is desired the following two escape sequences are valid inside an fs:
\{
and\}
. They are only valid in the string portion of an fs. Using them anywhere else results in a syntax error.The curly brackets may also contain a tag that is separated from the expression with a colon (
:
). The tag is optional but if a colon is present it may not be empty.The fs above evaluates to the following expression:
The returned string contains everything besides the curly brackets and their contents.
The expressions are returned inside the slice of
fsArgument
's. The length of this slice may be0
but the slice may not benil
.The expressions are evaluated in the order they appear in the fs.
Similarly how fs's mirror string literals rfs's mirror raw string literals. rfs's may span multiple lines and contain expressions and tags the same way fs's do. They can however not use escape sequences the same way raw string literals can't. The same example above but using a rfs looks like this:
"{"{"}"
is a little confusing due to the lack of syntax highlighting so I will explain it going from the outside inwards:""
are literal double quotes{}
introduce an fs argument""
is a string literal{
is an open curly bracket inside the string literalThis is necessary to recreate the original fs example exactly and because the escape sequence for a literal open curly bracket is not usable in an rfs.
It evaluates to the following:
It would include the new builtin type and the two new literal's. It is not necessary however to specify the way every type get's formatted or even mention the
fmt
package.C style formatting is easy and well known but it can get awkward really quick and become difficult to read and maintain. Since there is a large gap between where you insert a value and actually provide it you have to constantly switch between the actual string and the argument list. To solve this you can use Go's format strings. They provide the values in the string itself so you can easily see where a value is inserted, what is is and can easily change it's location.
Not entirely. Since a new builtin type is added there might be conflict if there is already is another type with the same name.
Show example code before and after the change.
It provides an alternative to format strings (which is a library feature) but this is a change on the language level and can support a broader use case.
No.
Costs
Harder, since it's a new feature and every feature adds complexity and learn time.
However it might make it easier for programmers used to a language with string interpolation to pick up Go since they can use a similar feature instead of needing to learn C style format strings.
The compiler needs to be able to recognize the new syntax and compile it appropriately. The tooling needs to recognize it as well to provide syntax highlighting, formatting and auto completion.
All of them need to recognize the new syntax. gofmt in particular needs to be modified to format the expressions inside the fs's.
The compiler needs to be able to recognize the new syntax and compile it correctly. This should however not be a huge cost.
There is no additional run time cost. The change is cosmetic.
The compiler already includes most components to implement the new syntax. It needs new "context"'s for fs's and rfs's to recognize the two new escape sequences and check the expressions inside the curly brackets. It also needs to expand them to their full form.
Not yet.
The text was updated successfully, but these errors were encountered: