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: iota for strings (useful for enums) #32176

Closed
gjvnq opened this issue May 21, 2019 · 9 comments
Closed

proposal: Go 2: iota for strings (useful for enums) #32176

gjvnq opened this issue May 21, 2019 · 9 comments
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@gjvnq
Copy link

gjvnq commented May 21, 2019

Problem

We can write code like this:

const (
	MONDAY int = iota
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
	SUNDAY
)

But not like this:

const (
	MONDAY string = iota
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
	SUNDAY
)

Proposal

Make iota return strings with the same value as the const name.

Example, this:

const (
	MONDAY string = iota
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
	SUNDAY
)

Is equal to this:

const (
	MONDAY    = "MONDAY"
	TUESDAY   = "TUESDAY"
	WEDNESDAY = "WEDNESDAY"
	THURSDAY  = "THURSDAY"
	FRIDAY    = "FRIDAY"
	SATURDAY  = "SATURDAY"
	SUNDAY    = "SUNDAY"
)

Why?

Simple, it makes writing code that use such enums easier, less boring and less error prone.

One good example is writing code that deals with errors:

const (
	ERR_PASSWORD_TOO_SHORT string = iota
	ERR_SUPER_USER_PASSWORD_IN_USE
	ERR_FAILED_TO_VERIFY_PASSWORD_HIBP
	ERR_FAILED_TO_HASH_PASSWORD
)

Compatibility

Current Golang, gives this error when trying to compile code like the one proposed:

cannot convert 1 (type untyped number) to type string

As such I don't think that any old code will become incompatible.

@gopherbot gopherbot added this to the Proposal milestone May 21, 2019
@ianlancetaylor ianlancetaylor changed the title proposal: iota for strings (useful for enums) proposal: Go 2: iota for strings (useful for enums) May 22, 2019
@ianlancetaylor ianlancetaylor added the v2 A language change or incompatible library change label May 22, 2019
@deanveloper
Copy link

While I like the idea, what would const Test = iota be? iota should always be an untyped integer constant. Perhaps a different name would be more fitting.

@gjvnq
Copy link
Author

gjvnq commented May 22, 2019

If the type is not specified it becomes a number just like today.

I agree that a sperate name would be better, maybe siota (s meaning string) or str_iota or string iota (with a space)

I think the last option (string iota) is better because it does not risk backward compatibility problems. (What if someone has a variable named siota or str_iota)

@mvdan
Copy link
Member

mvdan commented May 22, 2019

Why declare enum values as strings? Generally, you just need the values to be unique and simple, so integers are fine. If you need to represent them as strings, you can use https://godoc.org/golang.org/x/tools/cmd/stringer.

@gjvnq
Copy link
Author

gjvnq commented May 22, 2019

Because printing strings is easier than ints. I don't need a conversion function or a mapping table to print my errors and understand them.

@mvdan
Copy link
Member

mvdan commented May 22, 2019

This is precisely what String() methods are for, which is what stringer produces. fmt.Println(someEnumValue) will work out of the box with stringer, just like any %s or %v formatting.

@deanveloper
Copy link

I think the last option (string iota) is better because it does not risk backward compatibility problems. (What if someone has a variable named siota or str_iota)

Making a new predeclared identifier doesn't introduce backward compatibility problems. iota is a predeclared identifier (rather than a keyword). Also, iota is used already in other programming languages to signify a number which increases with each variable declared, I wouldn't use iota to signify this too, nor would I use striota or siota or whatever else. I think it should have its own, independent identifier.

@mvdan is also right that code generation with the stringer command already takes care of this.

@griesemer
Copy link
Contributor

I would have sometimes liked a feature such like this, but more often than not, I wouldn't want the string to match my constant name exactly. Worse, if one changes a constant's name, for instance when changing whether a constant is exported or not, the string would change, too, which seems not a desirable feature.

It also seems a bit unfortunate to "reuse" iota for this purpose: iota right now has a very simple definition: it's the (untyped integer) index of the constant declaration (specification, to be exact) starting at the const keyword. Giving it an extra meaning here adds complexity to the language for a relatively minor convenience.

But most importantly, we do have the stringer command as pointed out by @mvdan, which specifically addresses this problem. For a typical use with plenty of constants that need string names, see for instance $GOROOT/src/cmd/compile/internal/syntax/tokens.go. Specifically, the -linecomment gives you extra flexibility in the choice of string representation.

I'm not in favor of this proposal.

@MichaelTJones
Copy link
Contributor

MichaelTJones commented May 29, 2019

it seems to me that the most natural way to do it would be to allow

const (
	MONDAY = string(iota)
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
	SUNDAY
)

which keeps iota unchanged and adds the cast. This compiles now and gives FRIDAY == "\x04", what is new is making the meaning of string in this context be "itoa".

@ianlancetaylor
Copy link
Contributor

Thanks, but we already have the stringer tool, and that seems like the right tool for this job.

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

No branches or pull requests

8 participants