There are 2 programming languages that I am into at the moment, Clojure and Go (http://golang.org/). They seem to be opposites of each other in many ways, how can I love both? Clojure certainly wins on elegance with the ability to create pure functions, its homoiconic structure (Clojure programs are represented by Clojure data structures), its simplicity and clarity (http://www.drdobbs.com/architecture-and-design/the-clojure-philosophy/240150710#). Clojure is beautiful and parentheses are beautiful IMHO. So why do I love Go so much? It’s not what I would call beautiful.
Here is the equivalent Go and Clojure code taken from http://blog.drewolson.org/blog/2013/07/04/clojure-core-dot-async-and-go-a-code-comparison/:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
for i := 0; i < 10; i++ {
go func(i int) {
sleep := time.Duration(rand.Intn(1000))
time.Sleep(sleep * time.Millisecond)
fmt.Println(i)
}(i)
}
time.Sleep(2000 * time.Millisecond)
}
(ns async-example.core
(:require [clojure.core.async :refer :all])
(:gen-class))
(defn -main [& args]
(doseq [i (range 10)]
(go
(Thread/sleep (rand-int 1000))
(println i)))
(Thread/sleep 2000))
Go looks like C. Old fashioned, some would say ugly C. This was my initial reaction to Go but something happened along the way. I found myself wanting to write Go, all the time. This must be the influence of my subconscious because consciously I should be wanting to write Clojure, after all functional programming just logically makes sense. Clojure is beautiful, the tools are great, the community is great, so why should I desire to write Go over Clojure (again note that writing Clojure is also great fun). So what about Go do I love?
I like type safety. I’ve written a lot of ruby and python and I've enjoyed both. I’m not a compiler zealot, I’ve been involved with huge, complex and very successful projects that use dynamically typed languages. However I have to admit that despite inconveniences and the occasional bit of clumsiness (go has int, int32 and int64 types for example), the compiler is great especially when you have a language and environment like go that is optimized for compilation speed (http://stackoverflow.com/questions/2976630/why-does-go-compile-so-quickly). It’s a big win when you can work at dynamic language repl speeds with a statically typed language.
I like Go’s coroutine based concurrency model. Clojure recently implemented a nearly identical model with core.async. I’m sure I’ll have fun with core.async when I get the chance to mess with it. See http://golang.org/doc/effective_go.html#concurrency. Here’s a bit of code that collects sensor and weather data and drops the combined data on a channel:
package main
import (
"<a href="http://github.com/snyderep/chariot_sensor_data">github.com/snyderep/chariot_sensor_data</a>"
"<a href="http://github.com/snyderep/weather">github.com/snyderep/weather</a>"
)
type combinedData struct {
Measurements *chariot_sensor_data.MeasurementData
Weather *weather.WeatherData
}
func collectData(dataCh chan *combinedData) {
// start collecting sensor data
measurementsChan := make(chan *chariot_sensor_data.MeasurementData)
go chariot_sensor_data.Listen(udpAddrS, measurementsChan)
// start collecting weather data
weatherChan := make(chan *weather.WeatherData)
go weather.GetPeriodicWeatherData(&weather.Point{40.134739, -75.205564}, weatherChan)
var w *weather.WeatherData
var latestWeather *weather.WeatherData
var measurements *chariot_sensor_data.MeasurementData
for {
select {
case measurements = <-measurementsChan:
dataCh <- &combinedData{measurements, latestWeather}
case w = <-weatherChan:
latestWeather = w
}
}
}
Go manages to avoid the traps of other languages like Java that are primarily written in an imperative style. There’s no inheritance for example, Go favors composition and functions are first class objects.
Maybe I’ll start dreaming in functions, the above imperative style code will then seem awkward and wrong. For now though it seems clean (not my code necessarily, just go code in general), easy and natural.
If you haven’t geeked out yet with Go, why not have a go? Sorry :) Start here:
http://golang.org/
http://golang.org/doc/install
http://tour.golang.org/
http://golang.org/doc/effective_go.html