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

x/tools/cmd/stringer: Generate a method to get the enum value (int) form its name (string) #13744

Closed
alvaroloes opened this issue Dec 27, 2015 · 4 comments

Comments

@alvaroloes
Copy link

Currently, the stringer tool generates the method func (t Type) String() string to get the string name of an enum value.

In several projects I have had the need of exactly the opposite: get the enum value from the string name (for example when parsing a flag or when reading a configuration file).
I have ended up using a switch or a map, but I don't like it as I have to manually maintain it when values are added/changed/deleted. So the next step is to auto-generate it, just like the stringer tool does.

I was wondering if adding this functionality to stringer would be adequate for you guys. In my opinion, it seems pretty convenient and fits very well in that tool. I am sure there will be other people in the same situation than me that will benefit from it.

A possible signature for the generated function could be:

func <Type>FromString(s string) (<Type>, error) {...}

// Or
func <Type>String(s string) (<Type>, error) {...}

For example, if the type is Pill the function would be

func PillFromString(s string) (Pill, error) {...}

// Or
func PillString(s string) (Pill, error) {...}

The implementation could leverage the same variable the stringer tool already generates (a string or a map, depending on the number of runs found in the enum values). This requires a deeper reasoning (maybe a switch is the best option here)
Having an error as a second return value is needed to notify about strings that do not belong to the enum type.

The code to add is relatively simple and I can contribute with the needed changes.
Before doing that, I would like to hear your opinions/suggestions and know if you finally agree.

@rsc
Copy link
Contributor

rsc commented Dec 28, 2015

/cc @robpike

@rsc rsc added this to the Unreleased milestone Dec 28, 2015
@robpike
Copy link
Contributor

robpike commented Dec 29, 2015

For the exact thing you're asking, this is reasonable, but the general problem is the one that is more useful and more intricate that the Stringer problem. The mapping is not a bijection because of duplicate values, an issue that is straightforward to address if one uses a map but Stringer tries hard to be very dense, data-wise. That requires some thought.

The exact name of the Go symbol is useful only in a narrow context unlikely to be relevant to users. Are "Aspirin" and "aspirin" the same? What about "ASPIRIN"? What about " Aspirin"? And so on. The answers to these questions will vary with the program and programmer. And as you mention, there is the question of how to handle erroneous values. Attempting to have Stringer address them will open a configuration can of worms that will take it far from its original purpose, which was a simple, well-defined tool that demonstrates the use of go generate.

So we're tipping into issues about cases and folding and white space and data structures and so on. This is not a flag for Stringer, this is a new tool.

@robpike robpike closed this as completed Dec 29, 2015
@alvaroloes
Copy link
Author

Thanks a lot for your time and explanation.

Now that I know the original purpose of the stringer tool (a simple, well-defined tool that demonstrates the use of go generate) and after thinking about the implementation details of my proposal, it may go out of that simple goal.

However, what I would really dislike is to have another tool just to generate the counterpart of stringer: it would duplicate de number of go generate calls, the number of generated files, etc.

So I will create a tool that extends the stringer functionality adding what I proposed.

Thanks again and keep making Go more awesome than it already is ;-)

@alvaroloes
Copy link
Author

For the record, here is the tool I finally created: https://github.com/alvaroloes/enumer

It's a fork of the Stringer tool, but adding the code to generate the "String to enum value" function and fixing all the test to make them pass.
If finally uses a map, but avoids generating new strings: it uses slices leveraging the variables already generated by the original Stringer code.

As I can't use the github "fork command" to fork only the Stringer tool, I had to copy and paste the code and then do the needed modifications. @robpike Please tell me if you have any inconvenience with that.

Thanks!

@golang golang locked and limited conversation to collaborators Dec 29, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants