On Fri, 21 Aug 2020 at 22:46, Ian Lance Taylor <[email protected]> wrote:
> Yes, there are various such possibilities.
>
> What jimmy frasche said above is correct: nothing changes in the case
> of a type switch of a type parameter. The code now knows the type
> list element that the type argument matched, but it can't do anything
> that it couldn't do anyhow.
>
I suspect that this would make the new type switch construct very much less
useful.
For example, it wouldn't be possible to specialize a vector operation to
use machine-specific operations on a vector without using unsafe.
It might be interesting to do a survey of some of the reasons that people
would wish to use a type switch on a type parameter and see if the proposed
construct would be sufficient.
Have you got an example of how it might be used?
cheers,
rog.
>
> Ian
>
> On Fri, Aug 21, 2020 at 2:43 PM Axel Wagner
> <[email protected]> wrote:
> >
> > also, of course, you could still use operators with them, while now also
> knowing the exact semantics of those operators (e.g. in regards to
> overflow), which might also be useful.
> >
> > On Fri, Aug 21, 2020 at 11:42 PM Axel Wagner <
> [email protected]> wrote:
> >>
> >>
> >>
> >> On Fri, Aug 21, 2020 at 11:30 PM roger peppe <[email protected]>
> wrote:
> >>>
> >>> On Fri, 21 Aug 2020 at 22:10, jimmy frasche <[email protected]>
> wrote:
> >>>>
> >>>> I'd assume that would fail to compile as you're returning a []T not a
> []int
> >>>
> >>>
> >>> If that's the case, then I'm not sure that such a type switch would be
> very useful. It would tell you what type the values are, but you can't do
> anything with them because all the values would still be of the original
> type.
> >>
> >>
> >> You can reasonably convert them to their underlying type and *then* use
> them as such.
> >> That would make it useful while not allowing what you posit.
> >>
> >>> I had assumed that the intention was that within the arm of the type
> switch, the switched type would take on the specified type.
> >>> That would allow (for example) specialising to use underlying machine
> operations on []T when T is a known type such as byte.
> >>
> >>
> >> It would, however, prevent you from calling methods on the type or pass
> it to a function taking an interface compatible with the constraint.
> >> Also, I shudder to even imagine how this could be put into a spec.
> >>
> >>>
> >>>
> >>>
> >>>> On Fri, Aug 21, 2020 at 2:07 PM roger peppe <[email protected]>
> wrote:
> >>>> >
> >>>> >
> >>>> > On Fri, 21 Aug 2020 at 01:28, Ian Lance Taylor <[email protected]>
> wrote:
> >>>> >>
> >>>> >> After many discussions and reading many comments, we plan to move
> >>>> >> forward with some changes and clarifications to the generics design
> >>>> >> draft.
> >>>> >>
> >>>> >> 1.
> >>>> >>
> >>>> >> We’re going to settle on square brackets for the generics syntax.
> >>>> >> We’re going to drop the “type” keyword before type parameters, as
> >>>> >> using square brackets is sufficient to distinguish the type
> parameter
> >>>> >> list from the ordinary parameter list. To avoid the ambiguity with
> >>>> >> array declarations, we will require that all type parameters
> provide a
> >>>> >> constraint. This has the advantage of giving type parameter lists
> the
> >>>> >> exact same syntax as ordinary parameter lists (other than using
> square
> >>>> >> brackets). To simplify the common case of a type parameter that
> has
> >>>> >> no constraints, we will introduce a new predeclared identifier
> “any”
> >>>> >> as an alias for “interface{}”.
> >>>> >>
> >>>> >> The result is declarations that look like this:
> >>>> >>
> >>>> >> type Vector[T any] []T
> >>>> >> func Print[T any](s []T) { … }
> >>>> >> func Index[T comparable](s []T, e T) { … }
> >>>> >>
> >>>> >> We feel that the cost of the new predeclared identifier “any” is
> >>>> >> outweighed by the simplification achieved by making all parameter
> >>>> >> lists syntactically the same: as each regular parameter always has
> a
> >>>> >> type, each type parameter always has a constraint (its meta-type).
> >>>> >>
> >>>> >> Changing “[type T]” to “[T any]” seems about equally readable and
> >>>> >> saves one character. We’ll be able to streamline a lot of existing
> >>>> >> code in the standard library and elsewhere by replacing
> “interface{}”
> >>>> >> with “any”.
> >>>> >>
> >>>> >> 2.
> >>>> >>
> >>>> >> We’re going to simplify the rule for type list satisfaction. The
> type
> >>>> >> argument will satisfy the constraint if the type argument is
> identical
> >>>> >> to any type in the type list, or if the underlying type of the type
> >>>> >> argument is identical to any type in the type list. What we are
> >>>> >> removing here is any use of the underlying types of the types in
> the
> >>>> >> type list. This tweaked rule means that the type list can decide
> >>>> >> whether to accept an exact defined type, other than a predeclared
> >>>> >> type, or whether to accept any type with a matching underlying
> type.
> >>>> >>
> >>>> >> This is a subtle change that we don’t expect to affect any existing
> >>>> >> experimental code.
> >>>> >>
> >>>> >> We think that this definition might work if we permit interface
> types
> >>>> >> with type lists to be used outside of type constraints. Such
> >>>> >> interfaces would effectively act like sum types. That is not part
> of
> >>>> >> this design draft, but it’s an obvious thing to consider for the
> >>>> >> future.
> >>>> >>
> >>>> >> Note that a type list can mention type parameters (that is, other
> type
> >>>> >> parameters in the same type parameter list). These will be
> checked by
> >>>> >> first replacing the type parameter(s) with the corresponding type
> >>>> >> argument(s), and then using the rule described above.
> >>>> >>
> >>>> >> 3.
> >>>> >>
> >>>> >> We’re going to clarify that when considering the operations
> permitted
> >>>> >> for a value whose type is a type parameter, we will ignore the
> methods
> >>>> >> of any types in the type list. The general rule is that the
> generic
> >>>> >> function can use any operation permitted by every type in the type
> >>>> >> list. However, this will only apply to operators and predeclared
> >>>> >> functions (such as "len" and "cap"). It won’t apply to methods,
> for
> >>>> >> the case where the type list includes a list of types that all
> define
> >>>> >> some method. Any methods must be listed separately in the
> interface
> >>>> >> type, not inherited from the type list.
> >>>> >>
> >>>> >> This rule seems generally clear, and avoids some complex reasoning
> >>>> >> involving type lists that include structs with embedded type
> >>>> >> parameters.
> >>>> >>
> >>>> >> 4.
> >>>> >>
> >>>> >> We’re going to permit type switches on type parameters that have
> type
> >>>> >> lists, without the “.(type)” syntax. The “(.type)” syntax exists
> to
> >>>> >> clarify code like “switch v := x.(type)”. A type switch on a type
> >>>> >> parameter won’t be able to use the “:=” syntax anyhow, so there is
> no
> >>>> >> reason to require “.(type)”. In a type switch on a type parameter
> >>>> >> with a type list, every case listed must be a type that appears in
> the
> >>>> >> type list (“default” is also permitted, of course). A case will be
> >>>> >> chosen if it is the type matched by the type argument, although as
> >>>> >> discussed above it may not be the exact type argument: it may be
> the
> >>>> >> underlying type of the type argument.
> >>>> >
> >>>> >
> >>>> > Here's one interesting implication of this: it allows us to do type
> conversions that were not previously possible.
> >>>> >
> >>>> > For example, if we have "type I int", we can use a type switch to
> convert some type []I to type []int:
> >>>> > https://go2goplay.golang.org/p/-860Zlz7-cn
> >>>> >
> >>>> > func F[type T intlike](ts []T) []int {
> >>>> > switch T {
> >>>> > case int:
> >>>> > return ts
> >>>> > }
> >>>> > return nil
> >>>> > }
> >>>> >
> >>>> > It seems to me that this kind of thing will allow us to perform a
> similar conversion (convert some part of the type to its underlying type)
> on any type.
> >>>> >
> >>>> > In the early days of Go, the spec allowed this kind of conversion
> as a normal type conversion. I wonder if it might be reasonable to revert
> to those more relaxed semantics. I think they're potentially useful, for
> example, when dealing with named types obtained from modules with two
> different major versions without incurring copies.
> >>>> >
> >>>> > Although in the above-linked issue Robert talks about runtime costs
> such as "possibly re-mapping method tables", I don't see that this would
> necessarily be the case. Thoughts?
> >>>> >
> >>>> > --
> >>>> > 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 [email protected].
> >>>> > To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/CAJhgacjL7p7qck%3DSO0Nz9f%2BKZw6MNcgkD5REXwSNK7_fCTXYQg%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 [email protected].
> >>> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/CAJhgacjTm%3DC-6f%2B4%2BA0HCTDT0_U7pQZOmRjShuzigdocDzAcww%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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/CAJhgacjmBVUxkT8LE3iS4Ae7Ykeo04y%2BJGg12jfFVCKqo-jLLQ%40mail.gmail.com.