Skip to content
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: indentation in multiline raw string literals #36863

Closed
RodionGork opened this issue Jan 29, 2020 · 6 comments
Closed

proposal: Go 2: indentation in multiline raw string literals #36863

RodionGork opened this issue Jan 29, 2020 · 6 comments
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Milestone

Comments

@RodionGork
Copy link

RodionGork commented Jan 29, 2020

At go 1.13 version and earlier raw literal can be multiline. However there is no way to indent continuation lines without adding spare spaces to it, e.g.

// printing help message on program parameters, for example
func printHelp() {
    fmt.Println(`Usage:
    ./program server [arg1]
    ./program client [arg2]`)
}

in this case .program... is indented compared to Usage by 4 spaces, which makes sense, though code is not indented nicely (we'd like Println args all be indented further). However if fmt.Println is enclosed in some block (e.g. if) during refactoring, even this indentation may change, which is not good.

Suggestion

It is possible (like in Scala) introduce the rule, that if continuation line of the raw literal starts with |, then spaces before it are skipped. So the snippet could be rewritten:

    fmt.Println(`Usage:
            |    ./program server [arg1]
            |    ./program client [arg2]`)

Here we have normal 8 spaces indentation for arguments (or we can align them with the opening parenthesis if such style is preferred).

(if the line should start with | character we simply shall use two of them)

This is slightly breaking change so we may want introduce "extended" version of raw literal, for example enclosed in double backticks, e.g.

    fmt.Println(``Usage:
            |    ./program server [arg1]
            |    ./program client [arg2]``)

UPD as both versions are "breaking" as pointed out by colleagues below, I think we'll need to use "triple-tick"*. Suggesting double tick I just thought no one will use it for empty literal... But of course this couldn't be granted... E.g.

    fmt.Println(```Usage:
            |    ./program server [arg1]
            |    ./program client [arg2]```)

Though I understand it is slightly against the idea of not having two syntaxes for almost same things...

@ianlancetaylor
Copy link
Member

See also #32590.

@ianlancetaylor
Copy link
Member

Both of your suggestions could break existing programs. I don't see how we could do them.

@ianlancetaylor ianlancetaylor changed the title [Proposal] Indentation in Multiline Raw Literals proposal: Go 2: indentation in multiline raw string literals Jan 29, 2020
@gopherbot gopherbot added this to the Proposal milestone Jan 29, 2020
@ianlancetaylor ianlancetaylor added v2 An incompatible library change LanguageChange Suggested changes to the Go language Proposal and removed Proposal labels Jan 29, 2020
@mvdan
Copy link
Member

mvdan commented Jan 29, 2020

I don't agree with this proposal overall, but to provide another angle to @ianlancetaylor's comment - it would be possible, I think, if this feature was turned on for a new Go language version in a module's go.mod. Existing modules and packages would not break on their own, as their language version would be older until changed. Though, granted, when updating the language version one could encounter very subtle breakages.

@RodionGork
Copy link
Author

Both of your suggestions could break existing programs. I don't see how we could do them.

Yes Friends, sorry. I suggest non-breaking form is if we use "triple-tick" - this couldn't be confused with empty tick literal, right?

fmt.Println(```Usage:
            |    ./program server [arg1]
            |    ./program client [arg2]```)

@magical
Copy link
Contributor

magical commented Jan 31, 2020

@mvdan The language version is not carte blanche for language changes, though many people seem to think it is.

In Proposal: Go 2 transitions, Ian lays out the conditions for which the language can be safely evolved. In particular, they propose that additions and removals from the language would be okay, but redefinitions would not. The danger is that code could silently change meaning depending on the language version, and the compiler would not be able to detect code compiled with the wrong version. It would lead to "subtle breakages", as you put it.

A redefinition is a case where we have code that compiles successfully with both versions 1.N and version 1.M, where M > N, and where the meaning of the code is different in the two versions. [...] The complexity of a redefinition is, of course, that we can no longer rely on the compiler to detect the problem. [...] The only possibility would be to let programmers set the language version. [..] Of course, setting such a version would be error prone. [...]

I think the only feasible safe approach is to not permit language redefinitions.

Since this proposal would silently change the meaning of raw string literals, i don't see how it can safely be adopted as originally proposed.

The triple-tick variant would introduce a new syntax, so it would be a language addition rather than a redefinition, which should be safe.

@ianlancetaylor
Copy link
Member

This basic idea is discussed in various ways in #32590. Closing this issue as a dup of that one.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Projects
None yet
Development

No branches or pull requests

5 participants