Hi, Robert, Thanks for the quick replies. Let me address each of your points:
"Slice indexes are ints" is clearly true in the current language definition. From a pure language standpoint, one might assert that any index type other than plain int requires a map. However, if one has a data structure indexed by (small positive) typed integers, it is unrealistic to suggest using a map for storage of it when a slice is dramatically more efficient in both space and time. I wrote up this potential proposal because my colleagues and I have tripped over this issue multiple times in real-world applications. What I'm suggesting may be covered by generics if and when they ever happen, but considering that generics are a breaking change and are years away at best, they are not relevant to the evaluation of a small, backward-compatible change. As for the simple structs like EventList: they don't solve the problem of excess type casts; they merely move it to a different part of the code. In fact we do use encapsulating structures, but I omitted them from my writeup for clarity. As a separate, straw-man example, consider the common case of defining an enumerated integer type: type MyEnum int const ( EnumVal1 MyEnum = iota EnumVal2 EnumVal3 ) Once again, if one needs a data structure indexed by MyEnum, it makes much more sense to define it as a slice rather than a map. The use of iota quite literally guarantees that the values are suitable for slice indexing. I'm simply trying to alleviate the need for excess, error-prone casting when doing so. Regards, Steve On Sun, Feb 2, 2020 at 6:37 PM Robert Engels <reng...@ix.netcom.com> wrote: > One last point, if you are interested in type safety, why not create > simple structs like EventList to encapsulate the indexing, etc. Trivial and > can be done today. > > On Feb 2, 2020, at 8:28 PM, Robert Engels <reng...@ix.netcom.com> wrote: > > > Also, what you are asking for I believe is covered by generics. > > On Feb 2, 2020, at 8:17 PM, Steve Roth <st...@rothskeller.net> wrote: > > > Oh, please, Robert. No need to be condescending. I know perfectly well > how to use the value when that's what I want. Often it is not. The > examples that I cited are such a case: we are adding the IDs of the events > — the indices of the slice — to the person.Events field. If you don't like > my example, take a look through the standard library code: you'll find a > great many instances of range loops using only the index. > > Regards, > Steve > > > On Sun, Feb 2, 2020 at 5:56 PM Robert Engels <reng...@ix.netcom.com> > wrote: > >> You are using range incorrectly - you are using the index not the value. >> >> See https://tour.golang.org/moretypes/16 >> >> On Feb 2, 2020, at 7:39 PM, Steve Roth <st...@rothskeller.net> wrote: >> >> >> Greetings, >> >> I'm considering submitting a proposal for a language change, and would >> like some informal feedback on the idea before engaging the formal >> process. The idea being proposed here is intended to improve type safety >> by removing the need for some error-prone type casting. It is a backward >> compatible change. >> >> Consider a body of code that works with people and events. Both are >> identified with integer IDs; in order to prevent them being used in the >> wrong contexts, they are given specific integer types: >> type EventID int >> type PersonID int >> Assume also that people have lists of events they attend: >> type Person struct { >> Events []EventID >> } >> The code maintains slices of each type: >> var events []*Event >> var people []*Person >> When indexing into those slices, one can use the appropriate ID type: >> var eventID EventID = 3 >> println(events[eventID]) >> However, iterating over these slices requires casting in the current Go >> specification: >> for eventID := range events { >> // eventID here has type int, not type EventID >> person.Events = append(person.Events, eventID) // compile error, wrong >> type >> person.Events = append(person.Events, EventID(eventID)) // cast required >> } >> In cases where the event ID needs to be used inside the loop, it has lost >> its type safety. It has to be casted back to the type it is supposed to >> have. And that casting is error-prone; I could easily cast it to PersonID >> by mistake. This seems to be a noteworthy gap in type safety. >> >> My proposal is to allow this construction: >> var eventID EventID >> for eventID = range events { >> // eventID here has type EventID >> person.Events = append(person.Events, eventID) // accepted by compiler >> } >> Phrased more formally: a slice range operator can be assigned to a >> variable of any integer-derived type, not just "int". If this were done, >> error-prone casting could be avoided. >> >> Admittedly, there is still room for error here, since it would be >> possible to write >> var eventID PersonID >> for eventID = range events { >> // eventID here has the wrong type PersonID >> person.Events = append(person.Events, eventID) // compile error, wrong >> type >> } >> However, this error seems far less likely that a mistaken cast. And >> since there's no expectation that casts should be needed, the compiler >> error would cause greater scrutiny leading to fixing the real problem. (In >> any case, I don't wish to propose the (much larger and more impactful) >> change of having slices with typed indices.) >> >> I believe this proposal would significantly improve type safety in >> programs that work with multiple integer-derived types (such as most >> anything working with a relational database that prefers integer primary >> keys). I also believe it is backward compatible since it does not change >> the semantic of any existing code; it just adds a semantic to code that >> currently would not compile. >> >> I solicit the community's feedback. Should this proposal be formally >> submitted? >> >> Regards, >> Steve >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/CAAnpqKHS%3D2z0ZbNVSrULXLLGz%3DhAqpmrsLieciFu8L6%3DAn%3DLHA%40mail.gmail.com >> <https://groups.google.com/d/msgid/golang-nuts/CAAnpqKHS%3D2z0ZbNVSrULXLLGz%3DhAqpmrsLieciFu8L6%3DAn%3DLHA%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> >> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CAAnpqKEEOPicjwD%3Dmy08ORMzOwFiMFy4F%3DG3L9bdLFfbbsnHWA%40mail.gmail.com > <https://groups.google.com/d/msgid/golang-nuts/CAAnpqKEEOPicjwD%3Dmy08ORMzOwFiMFy4F%3DG3L9bdLFfbbsnHWA%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/75113376-DE42-4B0E-BF0E-456AC8D44418%40ix.netcom.com > <https://groups.google.com/d/msgid/golang-nuts/75113376-DE42-4B0E-BF0E-456AC8D44418%40ix.netcom.com?utm_medium=email&utm_source=footer> > . > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAAnpqKGF20ofxGg1ixQUXEgCkoBiBwKhece6YM8oxpOBEExO2w%40mail.gmail.com.