Lisp and Brain Neurochemistry
Lisp changes the way you think.
I could leave it at that, and this would be the world’s shortest blog entry.
Or, I could write a longish exposition, with code walk-throughs, of a recent experiment I’ve done with solving a programming puzzle using first the object-oriented way, then more of a data-first, functional way.
The former sounds too cryptic. The latter feels a bit complicated. (I’m the kind of person who loses interest in a problem once it has been solved). But, the lessons I’ve learned are priceless. They are a paradigm shift (tired as it sounds) in my ability to write programs and solve problems.
(The short story is that functional programming wins. I was using Ruby, a hybrid language that lets one emphasize either the OO way or the functional way in the scope of a problem. This is perhaps Ruby’s greatest strength: one can hybridize styles on the fly. But the experiment itself was inspired by my recent exposures to Clojure, Lisp, and Rich Hickey’s talks on Clojure, state, simplicity, and functional programming).
So, in the name of contributing with something constructive and not being a “knowledge sink”, here’s a version that strikes a middle ground. It’s a list of principles and observations written in a short, koan-type style. No in-depth explanations are given; no examples. Just sharp arrows pointing to the truth.
When confronted with a problem for the first time, answer three questions first: 1) what is the data we’re dealing with; 2) how is this data represented; 3) what are the main functions we need to turn this data into a solution. Data and functions are the core of any solution.
Run your program against a real data set as early as possible.
Just because the problem can be reduced to graph theory doesn’t mean we need graph objects or node or edge objects. By putting functions first, we can solve the problem in a leaner way, without adding a new level of abstraction.
Objects = state, behavior, identity. Here’s how to create nicer smelling objects: get rid of state first. Minimize variables, all kinds of them. Behavior is methods. Simplify these by designing them for chainability. This way, you force them to return values. Functions operate on data. Then, decide which ones to put outside of objects. What is left is identity. It then becomes the sum of that object’s properties.
Favor data literals over data objects or variables (i.e., not a string variable, but a literal string).
Use data structure literals liberally. Data structure literals (arrays, hashes, sets) are valuable because they reveal data and the containing structure in the context in which these appear. It is easy to see both structure and the values it encapsulates. This makes for more transparent programs and easier reasoning. Use data structures to expose data, not hide it.
Favor functions that take a collection and return a new one.
Bring data and data structures to the fore of your program.
At some level, any computer works by manipulating 0’s and 1’s. At some level, any object works by manipulating data structures: arrays, hashes, sets. Also at some level, any object works by manipulating strings and numbers (primitive values). Therefore:
When solving a problem, first compose a solution using these three core data structures and their combinations (array of hashes; hash of arrays; array of arrays). Resort to creating objects when this approach results in more complexity than needed. For example, you have an array of arrays that is n levels deep. At some level < n, you need a different structure because the arrays below that level need to be grouped according to other criteria. Create a record to contain those arrays.
When solving a problem, make functions operate on primitive data types to the extent possible. Replace objects and records with their string or numeric representations. Powerful functions operating on primitive values are a great way to prototype any algorithm. They are a great way to come to the core of the problem quickly and head-on.
I'm morphing into a Lisp hacker. I'm shapeshifting. God help me.