-
Notifications
You must be signed in to change notification settings - Fork 18k
Proposal: go/token: add Export and Unexport #32625
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
Comments
I forgot to mention - I'm of course open to suggestions when it comes to the package for this. I thought of |
The implementation above does not work for unexported identifiers that have no upper-case equivalents, like CJK languages. We've encouraged a "soft standard" of using X for those if needed, but then Export(中国) = X中国 but Unexport(X中国) = x中国, so they are not inverses. I'm also bothered by your example Unexport("URLFoo") => "urlFoo" (hard to figure out how to know to do this) or "uRLFoo". This doesn't seem like it is a well-formed operation. When you have a name you either generate an exported or unexported identifier to begin with. What is the use case for this operation? Is it well-enough defined to merit being in the standard library? In contrast, #30064 was very well-defined inspection of these, not modification. /cc @zombiezen for wire's use case |
The test cases for the Wire's generated code requires a bunch of temporary variables of distinct types. In early versions of the tool, the temporaries were very unhelpful (e.g. |
Ah, I hadn't thought about that. It certainly makes the problem even trickier. In a way, it will would make the API a bit more confusing. On the other hand, it can be used as an argument that even more (all?) of the implementations out there are wrong.
I only brought up this point to clarify that the API wouldn't try to do anything fancy here. So it would simply convert
Code generation, similar to Wire's use case. For example, in the chromedp link I gave above, we code generate a list of exported devices via their names. The original names aren't exported, so we must do that operation. I agree with you that the two operations here aren't well understood generally. Perhaps that means the APIs shouldn't exist. That still worries me, though, because of all the misconceptions and wrong implementations out in the wild. |
@mvdan, it's not that the operations aren't well understood. It's that they are fundamentally not well-defined. They depend on knowledge of the underlying human language, which is quite complex. I looked more carefully at the three examples given earlier. Wire. I don't think wire supports the argument that a general library is needed. The
The Chromedp. Another motivating example was a use in chromedp, which says:
The claim was that the second line is wrong. But the first line strips out any non-ASCII-alphanumeric characters, so the second line is correct as written. The domain-specific knowledge here (in particular, that the input is not general text but is a specific JSON structure](https://raw.githubusercontent.com/GoogleChrome/puppeteer/master/lib/DeviceDescriptors.js)) makes this code fine. A general solution token.Export would not have this knowledge. Go-endpoints. The use of strings.Title may be wrong, but since the input is multiple words, using token.Export would not be any better, unless token.Export handled conversions like What I see from these three examples is that conversion between naming styles is sometimes unnecessary and often requires other adjustments throughout the name. It looks like token.Export is difficult to define in general, and on top of that would rarely be sufficient on its own. And we have zero examples of needing token.Unexport. |
Fair enough, I agree that this isn't clearly a good idea. I've become less sure about this idea over the past few months. |
Summary
I propose adding two functions to the package's API:
Current situation
With #30064 merged, we already have some operations to deal with identifiers and names in
go/token
, such asIsIdentifier
andIsExported
.Another common need is to export or unexport a certain name. I've personally implemented either of those functions a handful of times over the years, and I can easily find implementations in popuar projects like this one.
However, I've also seen plenty of bad implementations. For example:
A very quick google search yielded an example of
Title
in a google-owned repository. And the last time I've seen the first mistake is here today, which made me think filing this proposal was worthwhile.Implementation
The correct implementation of each func is just two lines, but it's easy to forget about unicode, or to fall for the "false friend" that is
strings.Title
. Moreover, I think the API names would make code expressive and self-explanatory.One detail to keep in mind is that some implementations, like
google/wire
's I linked first, handle prefixes like acronyms separately. For example, I believe they would unexportURLFoo
asurlFoo
.However, I don't think this should be within the scope of
token.Export
; there isn't a way to impement this easily, covering all cases. A user can always implement this on top oftoken.Export
by replacing certain well-known prefixes with their unexported counterparts.If this proposal is accepted, I'm happy to upload a CL for Go 1.14.
The text was updated successfully, but these errors were encountered: