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: file scope #35387

Closed
seebs opened this issue Nov 6, 2019 · 8 comments
Closed

proposal: file scope #35387

seebs opened this issue Nov 6, 2019 · 8 comments
Labels
Milestone

Comments

@seebs
Copy link
Contributor

seebs commented Nov 6, 2019

What version of Go are you using (go version)?

1.13

Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

N/A, is proposed change

What did you expect to see?

Periodically, the question comes up of wanting some way to have sub-scopes, or to access file scope. (#7429 points out that file scope sort of exists, you just can't use it much).

The basic use case is: You want a thing to live inside a package, not in another package, because you want access to the package internals, but you have your own Even More Internals that you don't want exposed to the rest of the package -- possibly simply because you don't want to worry about name clashes.

For an example of the kind of workaround that exists, consider this example:

https://play.golang.org/p/WAuGTEHwiPg

This seems reasonable-ish, but it creates a subtle problem: I don't think the compiler can inline method values, and there's no other way I can see to get a function that you can call directly that knows about an implicit context it has which is a distinct namespace. (The lack of inlining hardly matters for some things, but for some performance-critical stuff on hot paths, it'd probably be bad.)

I have a definitely-unusable proposal for this, but don't see how to fix it. I am gonna go ahead and file this, because maybe someone will see an obvious fix, and if not, hey, every time someone asks for file-scope access, you can point them at this.

Proposal:

Just as capital letters represent exported names, and lowercase indicate unexported names, _ as the first character of an identifier is even more lowercase, and indicates a name which is only valid within the source file containing the declaration.

Problems with the proposal:

  1. No way to disambiguate the names if two files in the same package declare the same name. And names can leak; you could have two files provide identically-named implementations of an interface.
  2. Existing code uses _ as a prefix already. (Although a quick check through the go corpus suggests that it's never used to refer to
  3. Possibly a bad idea to add another source of complexity.

But I have thought about all the things like adding namespaces or modules or whatever that I've seen used to address this, and I think they all fundamentally run into "this is too hard to think about and requires too much context to interpret", while a variable naming convention allows you to see the thing instantly. And I've seen larger things run into problems with difficulty making sure names don't clash with each other within a package, but not want (or be able to) split the package cleanly.

A working solution might involve some other character. Someone in the performance channel on gopher slack suggested (jokingly) using unicode subscripts. I could also imagine \ being repurposed but I'm pretty sure everyone would hate that, and anyway lots of Go programmers are old enough to know that \u is actually an uppercase u. @?

@gopherbot gopherbot added this to the Proposal milestone Nov 6, 2019
@robpike
Copy link
Contributor

robpike commented Nov 6, 2019

One of Go's great clarifications compared to its ancestors is the simplicity of its scoping rules. Let's not complicate them again.

@seebs
Copy link
Contributor Author

seebs commented Nov 6, 2019

I seem to alternate between thinking that and thinking "okay, but surely file scope wouldn't break anything" on about a half-hour cycle right now.

@ianlancetaylor ianlancetaylor added v2 A language change or incompatible library change LanguageChange labels Nov 6, 2019
@ianlancetaylor
Copy link
Contributor

Quite similar to #33202.

@networkimprov
Copy link

I already use this very naming convention (as part of a longish ruleset for identifier names).

@maj-o
Copy link

maj-o commented Nov 7, 2019

The naming convention is usual for other languages private members.
And maybe Mr. Pike has the right view.
I also ran into that problem and wished just to be able placing a block

{
...
}

surrounding the file context
Example:

import ( ... )
var ( ... )  // global in package

{
    var ( ... ) // just in this scope (if this goes until EOF, then this is a file-scope)
    
    ...
}

I do not know, if there can be a clear rule: If You got into this problem Your package is to big.
But yes, there have been packages where findig the right names took some time.

@ianlancetaylor
Copy link
Contributor

Based on the discussion above, particularly #35387 (comment), and the similarity to #33202 which was declined, this is a likely decline. Leaving open for four weeks for final comments.

@seebs
Copy link
Contributor Author

seebs commented Nov 27, 2019

I think I'm mostly convinced. I've had cases where it would really help to be able to embed a hunk of code that has a private namespace somehow, but in practice, I think either there's a tolerably effective way to do it with livable costs, or it's important enough to put up with the extra workload, and as noted, other tools could check for this.

A specific example that has been in my head some is modernc.org/b:

https://godoc.org/modernc.org/b

This has the option of generating a concrete/non-interface form of the code, suitable for embedding in another package -- but then has the problem that it's defining single-letter names that become package-scope. But that could be addressed by updating the source to use more descriptive names...

@rsc rsc added this to Final Comment in Proposals (old) Nov 27, 2019
@rsc rsc moved this from Final Comment to Hold in Proposals (old) Nov 27, 2019
@rsc rsc moved this from Hold to Final Comment in Proposals (old) Nov 27, 2019
@rsc rsc removed this from Final Comment in Proposals (old) Nov 27, 2019
@ianlancetaylor
Copy link
Contributor

No change in consensus. Closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants