Blah Abstract
So displaying my ignorance to the world, I am taking the chance that some of this will be useful as notes in the future. Being wordy, explaining things to myself is how it works. So, sorry to bore you if you already understand closures. Having a good teacher makes all the difference and right now my teacher is Mark McGranaghan. I learned about Go about 7 years ago when I first left enterprise computing and started with open source. I was hanging out in East Culver City behind See's with dudes whom I should find again. Anyway. One of those dudes was excitedly talking about what golang was good for, and primarily it was about Google finding a way to stop declaring headers etc as they had been doing with C and C++. It made execution of everything 20% faster (at least). Since I always loved Pascal and static typing, I was inspired by that feature of Go. It wasn't baked at the time. In the meantime, even though all of the utilities of Vertica were written in Python, my fearless leader chose Ruby for our cloud-native development. I liked Ruby (then) over Python, PHP, JavaScript and all the other minor languages. I never liked Java, and I never had enough use for C or C++. So while it took a while to learn enough Ruby gems to be dangerous, I loved the elegance of the language, even though it was desperately difficult for me to distinguigh its regular syntax to the DSL that my boss was inserting into the code. As I started writing Ruby, I fell under the spell of building classes into an elegant (so I thought) higher level syntax. Others on my team made it very top down like scripting with no frills. While I was happy about using pry for interactive debugging, I eventually consigned myself to needing JRuby to speed the bastard up. And of course by the time Spark came around and more 'data scientists' (one day I'll be more gracious) started sprouting wings, I had to defend Ruby against Python more often.
While I heard this and that over the years about Haskell and Clojure, I tried to stay disinterested. But I definitely liked the idea of functional programming. I haven't really thought much about polymorphism or inheritance since the 80s. Funny, people still respect Smalltalk. While our engineering team was mastering Scala en masse, I was happy doing more stuff with JRuby and andvanced SQL in Vertica, not to mention the cool orchestration stuff I could do with Docker (now that we were done with Chef and Veewee and VirtualBox) and Terraform. Not that I needed to get into those weeds. We had dedicated heads for that. I remained focused on replication of complex business rules and workflows in the data governance domain.
Now I'm rather sick of everything. So I'm doing Go for my own whatever purposes. I'm going to Go into the ground, like it was Java and C++ and C all put together. Which it is, as far as I'm concerned. Which means for the 3rd time, I'm going to recast all of my stuff into a better language. Hopefully for the last time. I will expect that everything will eventually have a Go translation, even Apache Beam which I care about.
Lede
Closures were easy to understand because I have had several situations where I was unable to articulate my need for exactly what they do and I wanted to do it. I can't remember precisely, but it was definitely a situation in which I didn't want to use globals but I felt stuck. Maybe when I see the old Ruby code I'll remember. I never got into passing blocks and yielding and whatnot, although I might have if it weren't for expedience and the convenient transom of my boss. But I understand closures now. Thanks Mark.
Code
// p.15 closures
// a closure is a first class function that allows the use of free variables. You
// use a closure to keep track of a set of variables that are declared within an
// outer function. such that subsequent calls to the function can operate on that
// set of retained variables as if they were globals. They are not, however. They
// are local to the closure even after it has finished executing. The variable
// space is retained in the definition space of the closure.
package main
import "fmt"
func say_hello(msg string) {
fmt.Println(msg)
}
func return_anon_func() func(string) {
// return anonymous function
return func(msg string) {
fmt.Println(msg)
}
}
func int_seq() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
say_hello("Hello")
func(msg string){
fmt.Println(msg)
}("Hello Anonymous")
print_func := return_anon_func()
print_func("Hellow returned from Anon")
next_int := int_seq()
fmt.Println(next_int())
fmt.Println(next_int())
next_int2 := int_seq()
fmt.Println(next_int2())
}
That pretty much nailed it for me. I will conform my language to the formality in due time. But I get it. Happy Happy. Joy Joy.