> Go has automated delegation, and as we know, (automated) delegation IS inheritance [1, 2]. Some implementations of delegation are a bit more limited, some are a bit more expressive, but fundamentally they have the same purpose.
No it is not inheritance, and Go doesn't have automated delegation, it has type embedding.
Given struct A, if a function requires A, you can't pass any type B that embeds A, you must pass A.
> No it is not inheritance, and Go doesn't have automated delegation, it has type embedding.
Different names for the same thing.
> func acceptA(a A}{} // you can't pass B here
This says that the function isn't polymorphic in its argument, not that the types aren't polymorphic. Function resolution that is not polymorphic is not limited to Go, but occurs in inheritance-based languages, too. Example in OCaml:
class a = object method foo = 0 end
class b = object inherit a method bar = 1 end
let f (x: a) = ()
let () = f (new b)
You will get an error that the type of `new b` (= `b`) is not compatible with `a`, because they're not identical, even though `b` is a subclass of `a`.
If you replace the declaration of `f` with:
let f (x: #a) = ()
it'll work, because `#a` denotes a polymorphic type, matching `a` or any subclass of `a` (same as though you'd specify an interface in Go [1]). You can also cast the type explicitly to `a` to work around the error.
No, different names for completely different concepts.
> This says that the function isn't polymorphic in its argument, not that the types aren't polymorphic. Function resolution that is not polymorphic is not limited to Go, but occurs in inheritance-based languages, too. Example in OCaml:
Struct types in Go are not polymorphic in anyway period, the only way to achieve polymorphism in Go is through interfaces which are not concrete types, unlike classes.
> [1] Like Go, OCaml uses structural subtyping.
No it doesn't. There is no subtyping in Go. There is only type conversion and type assertion.
Whatever you wrote with OCaml is completely irrelevant to the discussion as the type systems are fundamentally different. but let's pretend it is.
It's interesting that you didn't bother try writing the equivalent of `let f (x: #a) = ()` in Go, because you CANNOT. An interface IS NOT a substitute for OCaml inheritance, as the later is more precise and specialized.
So no, Go doesn't support inheritance at its core. That's a false assertion. Go interfaces do not give a damn about what the actual implementation is, unlike OCaml sub classes.
There is. Go simply has structural subtyping [1] rather than nominal subtyping.
> It's interesting that you didn't bother try writing the equivalent of `let f (x: #a) = ()` in Go, because you CANNOT.
You forget that OCaml also uses structural subtyping. Writing `#a` is effectively the shorthand for the inferred interface. So you can write it also as:
let f (x: < foo: int; .. > ) = ()
where
< foo: int; .. >
is the interface of any class implementing at least a method `foo` of type `int`, i.e. what you'd write as
interface {
foo() int
}
in Go. You just don't in practice, because `#a` is both more convenient and readable.
> There is. Go simply has structural subtyping [1] rather than nominal subtyping.
No there is not, period.
interface {
foo() int
}
is not sub typing. but it's interesting how you move the goal post on each comment. You go from inheritance to sub typing to "structural subtyping". You're not interested in a serious discussion.
> is not sub typing. but it's interesting how you move the goal post on each comment.
I didn't say that this piece of code constituted subtyping. Here, I was refuting your specific claim that the equivalent of `f` cannot be written in Go.
> You go from inheritance to sub typing to "structural subtyping".
This is not how the thread went. I added a reference to structural subtyping as a purely explanatory footnote to illustrate a well-known similarity between OCaml and Go; subtyping had not been mentioned at all so far. Starting at that footnote, you introduced a digression by claiming that Go does not have subtyping at all.
The hell with your "assertion". Structural typing =/= structural subtyping, just like the presence of classes in a language in no way means that language supports inheritance.
> I didn't say that this piece of code constituted subtyping. I was refuting your specific claim that `f` cannot be written in Go.
It cannot since you had to add an interface to the mix, unlike with your OCaml example, which proves that go structs and OCaml classes are not similar in any way. Go structs do not support any kind of polymorphism unlike OCaml classes.
> Structural typing =/= structural subtyping, just like the presence of classes in a language in no way means that language supports inheritance.
Well, structural typing is used for two things, type equivalence and subtyping [1]. If it isn't subtyping, then the consequence would be that Rob Pike talked about type identity only, which doesn't make sense.
Let's pull in the definition of subtyping again:
> [S]ubtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability, meaning that program elements, typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype.
Now, one misunderstanding seems to be that you assume that I'm saying that B is or should be a subtype of A. Note that I never actually said that and it's not relevant; neither inheritance nor delegation necessarily create a subtype relationship. See "Inheritance is not subtyping" by Cook et al., a seminal paper in programming language theory [2].
Structural vs. nominative or nominal subtyping revolves around the definition of substitutability. With nominative subtyping, we have the case where a subtype relationship is constructed based on explicitly specified relationships between types identified by their names; structural subtyping exists when the type signature of the subtype conforms to the type signature of the supertype.
The latter is the case in Go. Somewhat simplified, the type of a struct (strictly speaking, of a pointer to an instance of that struct [3]) is the subtype of the type of any interface it matches.
> It cannot since you had to add an interface to the mix, unlike with your OCaml example, which proves that go structs and OCaml classes are not similar in any way.
This is because `#a` is a short-hand for "the interface of `a`". So, yes, the OCaml example does the same thing. You can reproduce it by removing the inheritance from OCaml, and it'll still work (or, without the `#`, still won't):
class a = object method foo = 0 end
class b = object method foo = 0 method bar = 1 end
let f (x: #a) = ()
let () = f (new b)
Note that the classes are completely independent; there is no inheritance at all. It's just that the interface of `b` conforms to the interface of `a`, and hence instances of `b` can be passed to functions expecting `#a`.
No it is not inheritance, and Go doesn't have automated delegation, it has type embedding.
Given struct A, if a function requires A, you can't pass any type B that embeds A, you must pass A.
func acceptA(a A}{} // you can't pass B here