[generics] Should convertibility and comparibility of two types be two kinds of constraints?

130 views
Skip to first unread message

T L

unread,
Jun 20, 2020, 11:26:08 AM6/20/20
to golang-nuts
For example, if there is a builtin convertible(from, to) constraint,
We can define a slice conversion function as

func Convert(type Ta, Tb converitble(Ta, Tb)) (avs []Ta, _Tb) (bvs []Tb) {
   bvs = make([]Tb, 0, len(avs)
   for _, v := range avs {
      bvs = append(bvs, Tb(v))
   }
   return bvs
}

We can use it as:

iValues := Convert([]int{}{1, 2, 3}, interface{}(nil))

T L

unread,
Jun 20, 2020, 11:35:38 AM6/20/20
to golang-nuts
And
* should "embeddable" be one kind of constraints?
* should "has some specified fields" be one kind of constraints?

Bebop Leaf

unread,
Jun 20, 2020, 1:10:29 PM6/20/20
to golang-nuts


> And
> * should "embeddable" be one kind of constraints?

Would you elaborate what do you mean by "embeddable"?

As for the other 3, I agree it would be good to have them as constraints.

Ian Lance Taylor

unread,
Jun 20, 2020, 4:48:07 PM6/20/20
to T L, golang-nuts

Ian Lance Taylor

unread,
Jun 20, 2020, 4:49:29 PM6/20/20
to T L, golang-nuts
On Sat, Jun 20, 2020 at 8:35 AM T L <tapi...@gmail.com> wrote:
>
> And
> * should "embeddable" be one kind of constraints?
> * should "has some specified fields" be one kind of constraints?

Being able to express every possible language concept in a constraint
is not a goal.

Also, this kind of extension can typically be added later.

Ian


> On Saturday, June 20, 2020 at 11:26:08 AM UTC-4, T L wrote:
>>
>> For example, if there is a builtin convertible(from, to) constraint,
>> We can define a slice conversion function as
>>
>> func Convert(type Ta, Tb converitble(Ta, Tb)) (avs []Ta, _Tb) (bvs []Tb) {
>> bvs = make([]Tb, 0, len(avs)
>> for _, v := range avs {
>> bvs = append(bvs, Tb(v))
>> }
>> return bvs
>> }
>>
>> We can use it as:
>>
>> iValues := Convert([]int{}{1, 2, 3}, interface{}(nil))
>
> --
> 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...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1754a8a6-a496-4a51-bc3d-ddb2dc1be75ao%40googlegroups.com.

T L

unread,
Jun 20, 2020, 10:27:31 PM6/20/20
to golang-nuts
For example:

type Foo(type A interface{}, B embeddable) struct {
    B
   
    // ... others
}

T L

unread,
Jun 20, 2020, 10:29:50 PM6/20/20
to golang-nuts
What are the rationales behind this?

Ian Lance Taylor

unread,
Jun 21, 2020, 11:21:29 PM6/21/20
to T L, golang-nuts
I'm not sure I understand your question. The section I mentioned is
under "Issues". There is nothing here that seems to need a rationale.
It's an issue that needs to be considered before making a language
change proposal.

Ian

T L

unread,
Jun 22, 2020, 11:21:22 AM6/22/20
to golang-nuts
OK, I see.
it would be great if a "convertible" constraint is provided, so that
the example in the first comment of this thread will be possible.
Otherwise, by the current constraint capabilities, a conversion
callback function is needed in declaring and using the generic
slice conversion function, whereas the conversion callback
function is an unnecessary repetitiveness.

Example (by the current rules):

package main

import (
    "fmt"
)

func Convert(type Ta, Tb) (avs []Ta, cb func(Ta) Tb) (bvs []Tb) {
   bvs = make([]Tb, 0, len(avs))

   for _, v := range avs {
      bvs = append(bvs, cb(v))
   }
   return bvs
}

func main() {
    iValues := Convert([]int{1, 2, 3}, func(v int) interface{}{
        return v
    })
    bytes := Convert([]int{1, 2, 3}, func(v int) byte{
        return byte(v)
    })
    bytesSlice := Convert([]string{"abc", "xyz"}, func(v string) []byte{
        return []byte(v)
    })
   
    fmt.Println(iValues...)
    fmt.Println(bytes)
    fmt.Println(bytesSlice)
}

Example (if convertible constraint is supported)

package main

import (
    "fmt"
)

func Convert(type Ta, Tb convertible(Tb, Ta)) (avs []Ta, _ *Tb) (bvs []Tb) {
   bvs = make([]Tb, 0, len(avs))

   for _, v := range avs {
      bvs = append(bvs, Tb(v))
   }
   return bvs
}

func main() {

    iValues := Convert([]int{1, 2, 3}, interface{}(nil))
    bytes := Convert([]int{1, 2, 3}, byte(0))
    bytesSlice := Convert([]string{"abc", "xyz"}, []byte(nil))
   
    fmt.Println(iValues...)
    fmt.Println(bytes)
    fmt.Println(bytesSlice)
}

BTW, if types can be passed to functions as augments, just like the builtin new and make functions,
the code will be more clean:

    iValues := Convert([]int{1, 2, 3}, interface{})
    bytes := Convert([]int{1, 2, 3}, byte)
    bytesSlice := Convert([]string{"abc", "xyz"}, []byte)

Reply all
Reply to author
Forward
0 new messages