sorry, previous is v unclear as it's assuming a solution to question 1 in clarification on question 2. amended below...
On Mon, Jun 22, 2020 at 12:40 PM Jon Reiter <jonrei...@gmail.com> wrote: > On Mon, Jun 22, 2020 at 12:00 PM Ian Lance Taylor <i...@golang.org> wrote: > >> On Sat, Jun 20, 2020 at 10:48 PM Jon Reiter <jonrei...@gmail.com> wrote: >> > >> > the draft lays out an example function GeneralAbsDifference. these >> comments build around that. i wanted to see how far i could get towards >> working specialization within this framework. the baseline assumption is >> that when specialization is required today the acceptable amount of type >> switching/assertion goes up a bit. >> > >> > so the simplest variation is >> > func GeneralAbsDifference(a,b interface{}) interface{} { >> > ai, aiok := a.(int) >> > bi, biok := b.(int) >> > if aiok && biok { >> > return OrderedAbsDifference(ai, bi) >> > } >> > // repeat for all types >> > } >> > >> > that works but is, even given the qualifier above, not really >> acceptable. you can make it a bit cleaner with reflect but still, it's >> bad. changing interface{} to Numeric doesn't work with compile error >> "interface type for variable cannot contain type constraints". fair >> enough, although i'm not convinced no such useful check is possible at >> compile time. with that facility available it's debatable whether some of >> those otherwise-not-so-clean setups are worth it in exchange for only >> having to write the underlying absdiff() functions once each. >> > >> > if we pretend the arguments can be of type Numeric we can try our type >> logic as: >> > ao, aook := a.(OrderedNumeric) >> > ... >> > in hopes of getting a somewhat-cleaner arrangement. this, with a and b >> using interface{} so it could otherwise compile, returns the entertaining >> error message "OrderedNumeric does not satisfy OrderedNumeric." and it is >> true that type does not appear in the type list of the interface. in this >> case there are two arguments and we'd need to ensure they are of the same >> acceptable type. i was expecting this to compile and then to write some >> logic using reflect and see how badly it turned out. that's not an option. >> > >> > but consider this for a single-argument function. then there is no >> uncertainty -- the logic i'd need to write is straightforward and can >> surely be automatically generated. i think that is true whenever each type >> parameter specifies only 1 argument's type. multiple-argument >> generic-specialization would then require creating "tuple interfaces" that >> glue the params together but would be otherwise clean and explicit. it's >> certainly better than what you'd need to do today to handle any of this. >> > >> > so two specific questions: >> > - is there some part-way use of types in interfaces that can be used >> in non-generic function arg specs? in this case the return value would >> require it but in general arguments-only would be useful too. >> >> Possibly such a thing could be defined, but it's not in the current >> design draft. And I'm not sure it would help. If I write F(a, b >> Ordered) then both a and b may be Ordered, but nothing requires that >> they be the same ordered type. >> > > yeah agree i only see a simple way for 1 argument (maybe i did not express > that clearly). you could rewrite multiple arguments using generic lists i > guess, or explicit Pair, Triplet, etc types. > > >> >> > - at least for cases where no ambiguity exists is it possible for a >> type-containing interface to act like it's on it's own type list? >> >> I guess I'm not sure why you need this. If you have a type list, it >> seems feasible to type switch on each possible type. I'm sure I'm >> missing something. >> > > so the code looks like: > if x1,ok1 := a.(first) ; ok { > Generic1(x1) > >> } else if x2, ok2 := a.(second) { > Generic2(x2) > ... > } else { > // never get here as long as every type is covered > } > > but that "never get here" is only true as long as the if/elses match every > type in the type list. you could get halfway with something like: > for t := range reflect.TypesOnTheList(a) { // maybe > reflect.TypesOnTheList(reflect.GenericTypeOf(a)) > if t == A || t == B || ... { > if x,ok := a.(t) ; ok { > GenericFunction(x) > } > } else if t == C || t== D || ... { if x,ok := a.(t) ; ok { > GenericFunction2(x) > } > } > } > > this is a step more than syntactic sugar wrt the spec as it automates some > maintenance. with that function in reflect it's just convenience. the > reflect version here is similar to your "reflection on type arguments" > section and could be done that way too. here i think you can get the > compiler to reject GenericTypeOf() on a non-generic type and ensure the > loop always hits it's mark. > punting on question 1, you can do this with something like what is proposed in the reflection on type arguments section, i think quite safely. > > > >> >> Ian >> > -- 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/CABZtUk6sbKswtCXYCTxF40Db5yZx5CfPzahxh8rcp3DC7tdDsw%40mail.gmail.com.