*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.

Reply via email to