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.

Reply via email to