Closures versus Objects
Jul 26, 2017

For a recent project I’ve been working on, I had to deal will lots of small components, each with somewhat different behaviour, and had tried several times (unsuccessfully) to come up with a good design for them.

Solving such puzzles tends to depend surprisingly deeply on the programming language used: in C, you’d need to create an ad-hoc object system and muck around with function pointers. In Java and C++ you’d set up an elaborate class hierarchy. Both of them fairly tedious, to put it mildly…

In a scripting language, it’s much easier to play games with the data structures, due to their dynamic typing, and to use tricks such as monkey patching - Python, Ruby, etc.

And in JavaScript, there’s also prototypical inheritance, which lets you tweak methods on a per-object basis. This is very flexible.

Although all of these are doable, they tend to work on the basis of a very centralised mutable mindset. Allow me to clarify this:

OOP has objects with state and methods which use and operate on that state. This is a great way to tackle complexity, by offering encapsulation (hiding data differences) and polymorphism (hiding code differences).

Methods need a backdoor into the object they’re working for, using a “this” pointer. Because all of the state lives in the object.

Now imagine you need a new object variant which differs only in a single method, say calculating and tracking a running average.

This requires new state to hold that running average, which then gets updated on each call. With the object-oriented model, you need to extend the object, i.e. create a subclass which has that extra state, and then override the method to access that state - not the end of the world, right?

But step back for a moment to think what happened: just because a single method (and possibly a single object instance!) needs to track extra state, we have to come up with a new object data structure, even though it doesn’t concern or affect any other method, or state for that matter.

Assuming most non-trivial objects have lots of methods, why do we have to invent a new class, come up with a new name for it, or rely on (redundant) inheritance - just to make one method do something which requires purely local state?

Worse still, repeating the process a few times with several methods being extended independently: what sort of messy class hierarchy are we going to end up with?

There are GoF patterns to deal with this, but hey, there’s in fact a much simpler solution in languages which support a mechanism called function closures.

The idea is that functions can access the context in which they’ve been defined. Here’s an example in Go, which should be readable even if you haven’t ever used it:

var lastAvg int

func Average(x int) int {
    lastAvg = (9*lastAvg+x) / 10
    return lastAvg
}

Wait a minute: that’s silly. Using globals? Where’s the OO? Even C code can do this!

True. I only included the above to illustrate the weakest form of lexical scoping: access to a static / global variable from inside a function, to illustrate how a function can manage state, i.e. how it can access data for its own private use (this is not a closure!).

Now compare the above code to this:

func Averager() func(int) int {
    var lastAvg int

    return func(x int) int {
        lastAvg = (9*lastAvg+x) / 10
        return lastAvg
    }
}

This is a function returning a function and also a peek into functional programming. By calling Averager() (note the extra “r”), we get a function back which does averaging, using a state variable which is inaccessible from the outside (very OO-like!) and which has exactly the same signature as that first version, i.e. taking and returning an int:

var Average = Averager()
var result = Average(123);

Note that we can now also set up multiple independent averagers, again very OO-like:

var Average1 = Averager()
var Average2 = Averager()

var result = Average1(123);
... = Average2(456) // does not affect above result

One way to look at closures, is as functions which act as if an ad-hoc object has been created for them and passed in through some invisible mechanism (which is how closures are implemented under the hood).

So how does this fancy machinery help us w.r.t. the original problem of this post?

Some Go code to illustrate the approach:

type MyObj struct {
    ... state ...
    MyMethod func(int) int
}

func MakeNewType() *MyObj {
    o := new(MyObj)
    var lastAvg int
    o.MyMethod = func(x int) int {
        lastAvg = (9*lastAvg+x) / 10
        return lastAvg
    }
    return o
}

func Example() {
    myObj := MakeNewType()
    println(myObj.MyMethod(123))
    println(myObj.MyMethod(456))
    println(myObj.MyMethod(789))
}

This code is admittedly fairly contrived, but note how easy it is to create an object with a custom MyMethod just for this variant, and how the local state required for averaging is not part of the object. Only MakeNewType() knows about the extra state, introducing it just before it gets used. This approach is just as encapsulated and polymorphic as class-based OOP, without needing an elaborate class hierarchy for objects that require slight variations in behaviour (i.e. code).

Both Go and JavaScript support this type of closure as first-class citizens. In the next weeks, I’ll explore another language which encourages this technique - stay tuned!

For comments, visit the forum.

Another pile of books
Jul 19, 2017

Here are more books I’ve been reading recently, of the “techie” variety and a bit closer to the usual topics on this weblog.

For electronics, there’s really not much that can compare to “The Art of Electronics” by Paul Horowitz and Winfield Hill - 2015, 1225 pages, ISBN 9780521809269:

It’s not a book to read from front to back, but it really covers just about anything you might want to know about electronics. This new third edition shines in the numerous diagrams and tables of component listings and properties for today’s most common transistors, MOSFETs, op-amps, and all sorts of other foundational stuff.

Once you’ve got the basics, just open the book in a random spot and start reading - there’s fascinating information on just about any of the over a thousand pages.

To learn a bit more about the practicalities of radio electronics, I’m reading through another huge volme, called the “ARRL Handbook”, published by the American Radio Relay League - 2014, 1449 pages, ISBN 9781625950017:

There are updated versions of this classic work, but any recent year is fine - a lot of the technology and knowledge has been around for a long time and remains timeless. It’s chock full of introductory material and sample projects, ranging from very basic to astonishingly advanced.

The other books I’ve been reading, and in some cases re-reading, are all about the software side of things.

First of all, there’s “Thinking FORTH” by Leo Brodie - 2004, 313 pages, ISBN 0976458705 (seems to be out of print):

By now, it’s really a curious mix of archaic techniques and fascinating insights in the constant drive towards simple solutions by making Forth “fit” the problem (as well as re-defining a problem to better tie into it). A must-read if you’re interested in Forth, but do take some of it with a grain of salt…

To get more fluent in Go (the language, not the game), I’ve been leafing through “Go, the Standard Library” by Daniel Huckstep - 2012, 412 pages, available from LeanPub:

The Go library functionality is superb, not the mention the huge range of packages you can access with nothing more than an “import” statement and a go get ... command to checkout a recent version.

For actual day-to-day reference, I use the Dash documentation browser on macOS, which provides over 160 well-maintained documentation sets. It’s basically a local mirror of web-based information, with a very convenient and fast search interface.

And last but not least, I’ve been reading up again on ClojureScript, the language which marries functional programming with the browser: “ClojureScript Unraveled” by Andrey Antukh and Alejandro Gómez - 2016, 2014 pages, available from LeanPub:

In my opinion, there’s nothing which can even come close in terms of high-level abstraction for designing software - the required processor capabilities far exceed that of a microcontroller alas, so this really only has a use in the web browser (and on not-too-low-end Linux systems + NodeJS).

Once I get back to implementing browser-side front ends, I intend to have a very serious go at using ClojureScript together with Reagent, which is a wrapper around the amazing ReactJS library. Will be fun!

The above books are clearly just a personal choice, but I think each one of them stands out in the depth of material they cover and in their timeless content.

For comments, visit the forum.

A different mindset
Jul 12, 2017

One of the things I get to do on vacation, and especially while traveling by train, is reading (e-)books - tons of them, in fact.

I tend to read a lot all year round, technical articles, textbooks, techie weblogs, world news, and of course code… masses of code.

But on the road (track?), I prefer a different mindset, reading (i.e. devouring) thrillers, and … stuff that gives me new perspectives.

Here’s my selection of this year’s material, which ended up going in a pretty thought-provoking direction: our place in the world and the path we’re on. Heavy stuff.

Not strictly this year’s reading, although I only finished it this vacation: “Digitale Demenz” by Manfred Spitzer (in German) - 2014, 368 pages, ISBN 9783426300565:

The byline says it all: “How we’re making our kids crazy”. Smartphones and such…

The second book really blew my mind: “Sapiens: A Brief History of Humankind” by Yuval Noah Harari - 2015, 464 pages, ISBN 9780062316097:

It’s a fascinating view on the role of our species across all history, and what made Homo Sapiens so dominant and successful (at least in evolutionary terms). The magic word is storytelling - read the book, I can’t recommend it highly enough. Seriously.

In his second book, the story continues: “Homo Deus: A Brief History of Tomorrow” by Yuval Noah Harari - 2017, 464 pages, ISBN 9780062464316:

This one is very intriguing: a historian who identifies trends and dares to extrapolate them to the future? I found it to be a great analysis of where we are and the places we might be headed for. Tricky stuff.

Next on the list, this one again in German: “Evolution Ohne Uns” by Jay Tuck - 2016, 338 pages, ISBN 3864704014:

The byline says it all again: “Will artificial intelligence kill us?” - according to Tuck, we’re creating a perfect encyclopedia of all our knowledge, strengths, and weaknesses, in the form of the web - which can then be instantly devoured by AI when it reaches a certain level. And once that happens, it’ll be game over in the blink of an eye.

Can we avoid it? Consider “merely” asking the machine to calculate the digits of π to arbitrary precision, the AI then “deciding” that it needs more computing power, taking over most of the internet, performing its task as requested by redirecting all the planet’s energy to that task, and killing off humans and other life as side effect - oops?

And that’s where my last book comes in: “Daring Greatly” by Brené Brown - 2015, 320 pages, ISBN 9781592408412:

She also gave a few presentations on TED. It’s a wonderful story about what matters.

Sooo… that was quite some heavy reading while traveling in Germany and Denmark! As a tech geek, hopelessly infatuated with gadgets, algorithms, and circuits, I’ve now become a bit scared of where we’re headed.

Have we lost ourselves in technology?

PS. The next book on my list is probably: “Superintelligence”, by Nick Bostrom - 2013, 352 pages, ISBN 9780199678112.

For comments, visit the forum.

Weblog © Jean-Claude Wippler. Generated by Hugo.