|
|
Subscribe / Log in / New account

Go and Rust — objects without class

Go and Rust — objects without class

Posted May 21, 2013 6:01 UTC (Tue) by mmaroti (guest, #84368)
Parent article: Go and Rust — objects without class

The article does not mention the main difference between the Rust and Go object model:

1) In Rust you separately pass the virtual table pointers with the object pointers. So if Rust wants to store a vector of objects implementing the Shape interface, then you have to record both the virtual table pointer and the data pointer for each Shape. However, Rust stores a vector of Circle objects that implement the Shape interface by storing a single virtual table for circle and a vector of data pointers for each Circle. Haskell does the same (there interfaces are called type classes and implementations are instances).

2) Go stores the virtual tables together with the objects. This is how C++ and Java stores objects, so no matter if you have a vector of Shapes or Circles, both can be stored in a vector of data pointers.


to post comments

Go and Rust — objects without class

Posted May 22, 2013 8:19 UTC (Wed) by neilbrown (subscriber, #359) [Link] (3 responses)

Hi. Thanks for you comment. I'm not sure I follow you though. The two type systems look very much the same in this particular respect.

In Rust a pointer to a value is usually just to the value - no vtable is implied. To get a vtable,you use the "as" operator. "mycircle as Shape" becomes a pair of pointers, one to 'mycircle', one to a vtable which implements "Shape" for mycircle.
This is described in section "8.1.10 Object types" of the Rust reference manual, and seems to agree with what you said.

In Go, a pointer to a value is just to that value, no vtable. To get a vtable you need to convert it to an 'interface' type, such as by "Shape(mycircle)". This will compute (possibly at runtime) the vtable if it doesn't already exist, and will create a pointer-pair, just like in Rust. In Go you don't need the explicit cast. Assigning to an interface-type or passing as a parameter where an interface-type is expected are sufficient. This is a small difference to Rust where I think the "as" is required (not sure though).

More details of the Go approach can be found in http://research.swtch.com/interfaces
This seems quite different to your description of Go.

Go and Rust — objects without class

Posted May 22, 2013 20:40 UTC (Wed) by mmaroti (guest, #84368) [Link] (2 responses)

Hi! Thanks for the pointers and clarification. Yes, as you write, interfaces in Go and Rust are stored essentially the same: both a pointer to the vtable and a pointer to the data is stored. However, I am under the impression that the vtable is computed dynamically for each cast in Go and statically at compile time in Rust. I am going by these two sources:

http://smallcultfollowing.com/babysteps/blog/2012/04/09/r...
https://news.ycombinator.com/item?id=3749860

By these accounts you cannot do upcasts in Rust, so the vtables (the actual type of objects) cannot be computed at runtime. In Go, the vtables (actual type) of objects can be computed.

From my point of view it is an implementation detail whether a language is storing the vtable in the first field of the data object (the C++ way) or you pass the vtable pointer together with the data pointers (the Go way). The important point, that you try to cast from interface{} to any other interface.

By the way, does Go have polymorphic arrays, which would ensure that all objects in the array are of the exact same type, and only a single vtable pointer is stored together with a bunch of data pointers?

Go and Rust — objects without class

Posted May 22, 2013 23:04 UTC (Wed) by neilbrown (subscriber, #359) [Link] (1 responses)

  • Yes, the vtable (referred to in the page I linked as an 'itable') is computed dynamically at runtime in Go. However it is only computed once for a given interface/type pair - it isn't recomputed at each cast.
  • No, casts from an interface to a particular type (I call them downcasts, but you seem to call them upcasts) are not possible in Rust. The article mentions this in that Rust has no equivalent of Go's type assertion. You need to use an 'enum' type in Rust if you want that sort of functionality.
  • I see a couple of possibly-important differences between what you call the "C++ way" and the "Go way".
    • The C++ way doesn't scale well for tiny objects. The stored vtable pointer might be bigger than the rest of the object.
    • The C++ way requires a single vtable. I don't know how multiple interfaces work with that. The Go ways uses a different itable for each different interface, so multiple interfaces are trivial.
  • I don't think that Go supports polymorphic arrays as you describe.

Go and Rust — objects without class

Posted May 23, 2013 2:25 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

>The C++ way requires a single vtable. I don't know how multiple interfaces work with that.
Reserve the first slot in the vtable for interface lookup function, kinda like QueryInterface in COM.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds