Why Go don't allow convertion from two slice/array types whose elements are of same underlying elements.

193 views
Skip to first unread message

David DENG

unread,
Feb 22, 2013, 5:40:09 AM2/22/13
to golan...@googlegroups.com
e.g.
type S string
t := []string{"abc"}
var s []S = []S(t) // cannot convert t (type []string) to type []S

I think in the binary level, they are the same, so very easy for compiler. But if we have to do this manually, the code above has be changed to:

type S string
t := []string{"abc"}
var s []S = make([]S, len(t))
for i := range t {
s[i] = S(t[i])
}

Even the copy function cannot be used. This is very inefficient.

Why?

David

Maxim Khitrov

unread,
Feb 22, 2013, 7:05:37 AM2/22/13
to David DENG, golan...@googlegroups.com
On Fri, Feb 22, 2013 at 5:40 AM, David DENG <david...@gmail.com> wrote:
> e.g.
> type S string
> t := []string{"abc"}
> var s []S = []S(t) // cannot convert t (type []string) to type []S
>
> I think in the binary level, they are the same, so very easy for compiler.
> But if we have to do this manually, the code above has be changed to:
>
> type S string
> t := []string{"abc"}
> var s []S = make([]S, len(t))
> for i := range t {
> s[i] = S(t[i])
> }

You can do the conversion with unsafe and reflect:

https://code.google.com/p/go-sqlite/source/browse/go1/sqlite3/driver.go#150

- Max

Rémy Oudompheng

unread,
Feb 22, 2013, 7:23:45 AM2/22/13
to David DENG, golan...@googlegroups.com
I don't think there is a particular reason. For example, if S and T
are named types with identical underlying types, a *S can be converted
to a *T.

rsc proposed to add a reflect.Value.SetMem to allow "conversion" or
"cast" between types that are identical from a low-level point of view
but not convertible according to Go rules.

See https://groups.google.com/d/topic/golang-dev/87EB5TCzB0I/discussion
for the associated discussion.
I think it is still an interesting feature but the debate seems to have stalled.

Rémy.
>
> David
>
> --
> 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.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Hǎiliàng

unread,
Feb 22, 2013, 8:10:44 AM2/22/13
to golan...@googlegroups.com
It is called "contravariant", and there is also "covariant" that refers to the conversion from []S to []string.

All the languages that have these features also have sophisticated generic features, which Go 1 lacks. I guess this is the reason.

http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29

Hǎiliàng

Rémy Oudompheng

unread,
Feb 22, 2013, 8:26:23 AM2/22/13
to Hǎiliàng, golan...@googlegroups.com
On 2013/2/22 Hǎiliàng <hwan...@gmail.com> wrote:
> It is called "contravariant", and there is also "covariant" that refers to
> the conversion from []S to []string.
>
> All the languages that have these features also have sophisticated generic
> features, which Go 1 lacks. I guess this is the reason.
>
> http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29
>
> Hǎiliàng

The conversion from []string to []S has nothing to do with
contravariance, I think you are confusing with a different notion. If
you were to give it a name, both []string -> []S and []S -> []string
would be examples of covariance, not contravariance.

Also you seem to imply that S and string are different types in
nature, but they are not. They are both named types of the same kind.

Rémy.

Hailiang Wang

unread,
Feb 22, 2013, 9:16:47 AM2/22/13
to Rémy Oudompheng, golan...@googlegroups.com
I intended to give some references of covariant and contravariance
that I believe is relavant to this discussion.

Wikipedia:
* covariant: converting from a specialized type (Cats) to a more
general type (Animals).
* contravariant: converting from a general type (Shapes) to a more
specialized type (Rectangles)

In the example of this discussion, let's assume S is Url:
type Url string

Conversion from []string to []Url *is* converting from a general type
(strings) to a more specialized type (Urls).

Also, S and string are not of the same type (static type): they are of
the same *underlying* type "string", according to the Go spec.

The difference between Go and all the other languages is that Go's
type is flat, without hiearchy. The conversion might be simpler for
Go.

Hǎiliàng

Rémy Oudompheng

unread,
Feb 22, 2013, 9:38:58 AM2/22/13
to Hailiang Wang, golan...@googlegroups.com
On 2013/2/22 Hailiang Wang <hwan...@gmail.com> wrote:
> I intended to give some references of covariant and contravariance
> that I believe is relavant to this discussion.
>
> Wikipedia:
> * covariant: converting from a specialized type (Cats) to a more
> general type (Animals).
> * contravariant: converting from a general type (Shapes) to a more
> specialized type (Rectangles)
>
> In the example of this discussion, let's assume S is Url:
> type Url string
>
> Conversion from []string to []Url *is* converting from a general type
> (strings) to a more specialized type (Urls).

The Url type is not more specialized as the type "string". Both have
the same status and represent the exact same set of values. There are
natural arrows Url -> string and string -> Url, reciprocal to each
other. Only one of these arrows would exist if Url was a specialized
form of string.

Here we are talking about slices, and given a type S which is
assignable to T, the only sensible thing we can do is tranform []S to
[]T, so slices can only be covariant, but Go does not express this
covariance in its rules.

Rémy.

David DENG

unread,
Feb 22, 2013, 9:54:58 AM2/22/13
to golan...@googlegroups.com, David DENG
I think the conversion is quite safe, should not use unsafe and reflect.

Can I propose a feature of this?

David

Hailiang Wang

unread,
Feb 22, 2013, 9:58:30 AM2/22/13
to Rémy Oudompheng, golan...@googlegroups.com
What's interesting is the different perspective between us, though we
have the same understanding of Go spec.

You see the *implementation*, that S and string are exactly the same in memory.

But I see the *concept*. The reason that someone would define "type
Url string" is because Url is different with string, and more speical
than string: a url is a string, but a string is not necessarily a url.

Hǎiliàng

John Asmuth

unread,
Feb 22, 2013, 10:05:59 AM2/22/13
to golan...@googlegroups.com, Rémy Oudompheng


On Friday, February 22, 2013 9:58:30 AM UTC-5, Hǎiliàng wrote:
a url is a string, but a string is not necessarily a url.

I do not believe that this is a useful way of thinking about it, even if you could consistently apply the word "more general" if you really wanted to.

In go, writing "type A B" means create a type A with the same data representation as type B. As a result, you can convert them back and forth. It is not a more general B, since, for instance, it has none of B's methods.
Reply all
Reply to author
Forward
0 new messages