*generics :) > On Feb 2, 2020, at 9:27 PM, Robert Engels <reng...@ix.netcom.com> wrote: > > > I think the major difference is that by using EventID as a constrained type, > you are then attempting to constrain index values - for which there are no > constraints other than slice length. > > Similarly, using an enum as a slice index would NEVER be safe. Enums are > sparse. Slices are contiguous. Any safety here would only be by convention - > and subject to great runtime risk (invalid index). > > I really believe using EventList and the Iterable pattern will give you the > greatest type safety and “idiomatic Go” simplicity. > > As you state, you are already doing this (but you omitted it). The type casts > are zero cost. Can you explain why this pattern doesn’t work for you (other > than the common arguments for genetics)? > >>> On Feb 2, 2020, at 9:08 PM, Steve Roth <st...@rothskeller.net> wrote: >>> >> >> 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. >>>>> >>>>> -- >>>>> 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. >>>> -- >>>> 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.
-- 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/A6CFAACE-2DB7-4A15-8A57-17314446217F%40ix.netcom.com.