Tuesday, November 17, 2009

A Mental Model of Types and Methods in Go

I've been spending the past few days since Go's release wrapping my head around it. The language site has a lot of good information, but I wanted to write up my understanding of one part of the type system.

First off, while they're types in terms of syntax, I see Go's interfaces as semantically distinct; for most of this post, when I say "type" I mean a concrete or non-interface type.

Aside from those, Go has a lot of built-in types. To build a user-defined type, one simply aliases that type to a built-in type or to some other user-defined type. The built-in type defines the format of an instance in memory, but defines no methods. Methods are attached to user-defined types; which methods a type has may depend on various things I won't get into right now, but this set is fixed for any particular concrete type.

Interfaces act as a layer on top of user-defined types. A variable with an interface type can contain any instance of any concrete type whose method set includes all of the methods in the interface. Go is rather unusual in that no explicit declaration is necessary for a concrete type to implement an interface -- if the methods are there, the interface is considered to be implemented. Among other things, this means that an interface can be created after the fact to describe functionality common to several types, and all of those types will automatically be compatible with variables declared as instances of that interface.

This means that any particular variable carries three pieces of information. First, there's the actual value; this is not directly accessible via interface variables but present in all cases. Second, there is the runtime type -- that is, the concrete type of the variable; this is what reflect.Typeof will tell you about, and defines the method set that will be used. Finally, there is the compile-time type, which is either the runtime type or some interface it implements; this determines which methods can actually be called and whether access to the value is possible.

Each of these bits of information can be changed relatively independently. A type assertion can change the compile-time type without affecting either the runtime type or the value. A (non-numeric) conversion can change the runtime type as well as the compile-time type, as long as the in-memory representations are identical. And of course changes to the value will in general not affect either type associated with an instance.

One interesting result of this is that you can use conversions to swap out the method set of an instance in runtime. For example, sort.StringArray defines methods on a []string that define a particular sort ordering. One could easily write a ReversedStringArray type that induces a backwards sort. Applying conversions, it would even be possible to take the same array and sort it in different ways at different points in the program, all using the sort package, just by telling Go to treat the array as a different runtime type each time.

Friday, November 13, 2009

Thoughts on Go

Along with many other people, I've recently run into Go, a new programming language from Google. I think it's got a lot of potential, and I really want to play with the type system and see how it works out in practice.

I got it running on my server, and quickly got down to writing some thought-experiment code. Once I split the code out into packages, I had some initial difficulty getting it to compile. The Go source tree has some Makefile magic for that, but it presumes that you will want to install your packages into the $GOROOT/pkg directory for use after they're built, so I didn't want to use that directly. Luckily, another intrepid blogger saved me the trouble of figuring out how to build Go code manually.

Go is designed to be good for writing highly-concurrent network services. I think I'll try and bootstrap an XMPP server project in the language, if it feels fun to code the first bits.

Friday, April 24, 2009

Welcome

Welcome to Code Think.

Here, I will be chronicling some of my experiences in working on code, mostly open source code. By placing my thoughts on design and implementation in public, I hope to invite some scrutiny and constructive criticism. Ideally, some of this will also be useful to the people reading it. Finally, the blog will act as a record for future reference, so that any mistakes that are made do not get repeated.

A few topics/projects of interest, most of which are likely to get posts of their own at some point:
  • Ways to integrate Python and Vala together. There are two components to this. First, I want to assemble a toolchain for automatically exposing Vala classes as CPython extension types, possibly by taking advantage of PyBank. Second, I want to expose as much of the Python/C API itself to Vala, so that it is possible to write custom extension types with special behavior or performance characteristics in Vala.
  • Working on Concordance XMPP, which I want to see enhanced to the point where it will perform as a basis for an Atom over XMPP Pubsub implementation, among other neat things.
  • Playing with the Strophe JavaScript XMPP client library. There is potential for this to act as the base for some zero-configuration-required dynamic web application stuff, but only if it can do anonymous XMPP login and uses the XHR-via-IFRAME trick or some BOSH session multiplexing magic to allow browsers with small per-domain connection limits to have many tabs/windows open.
All three of the above are vaguely foundational in nature. Until such time as I have useful implementations running, I'll leave it as an exercise for the reader to determine what they might be foundations for.