I learned Common Lisp last summer. I had been using some combination of Python, C++, C, and Java for about 8 years, and I wanted to break out of my popular language box. I was more or less attracted to the “data as code” idea, but really it had a bunch of selling points that I would have appreciated:
- Its data was stored in the same structures as its program.
- It had macros that were powerful and simple. That’s huge coming from C++.
- It was REPL-based, something I never took advantage of with Python.
- You could create new code on-the-fly at runtime from lists.
- Completely dynamic and backed by garbage collection.
- The language itself is very mutable.
The sum of its parts was greater than anything that I had ever used before, and it quickly became my favorite language. I learned quite a bit about functional programming techniques, did some experimentation with image processing and database application programming, and worked through all of Graham’s ANSI Common Lisp and large swaths of Norvig’s Paradigms of Artificial Intelligence Programming.
Recently, a nagging though started to cross my mind: What if I didn’t go far enough to break out of my box?
That didn’t happen until two weeks ago, when I started porting Genesis, my toy genetic algorithm framework, to Clojure for fun. I wasn’t very aware of the features of Clojure: I knew that it was a Lisp on the JVM and that it supported Software Transactional Memory, but I didn’t think it would be that different from Common Lisp aside from Java interoperability.
To clarify, I expected that the primary method of manipulating Clojure would be list-based, and that it would still mostly turn a blind eye towards mutable data and multithreading issues, with the option of phrasing memory updates in terms of transactions if you were using multithreaded applications.
Clojure turned out to be different than any language that I had ever tried – save my forays into Haskell to grok enough syntax to follow sigfpe’s easier articles. If you trust the language and work with the core Clojure data structures, it takes a lot of the worrying about parallel programming out of your hands. Its creator, Rich Hickey, ended up with a language that has a good balance between functional programming and practicality. It is definitely a good Modern Programming Language.
You Said Something About A Box..?
Right, I said I didn’t go far enough outside of my comfort zone when learning Common Lisp. That’s really only half true.
From the perspective of programming, Common Lisp is a great language. Using the functional programming primitives provided on top of lists feels very natural, and I was able to work on complicated problems with relative ease. Even though I don’t use the macro system in Common Lisp very often, it usually provides a great fallback for either refactoring or changing the way the problem can be represented. The REPL is just icing on the cake.
However, not all is flowers and roses. Looking at Common Lisp from perspectives other than single-threaded programming, it begins to look mortal! For instance, the Common Lisp standard was written without a thought to having multiple threads of execution. Although most implementations provide extra support for multithreading, you’re back in the same locking boat that you were with any of the other popular languages once you need to share mutable data. Naturally, the syntax for things like grabbing mutexes is easier with Lisp than with other languages thanks to the “with-” design pattern for macro writing, but you’re not gaining much with respect to avoiding race conditions.
Looking at it from a data-processing perspective, functional programming is easy in Common Lisp, but it isn’t required at all. There’s nothing stopping the programmer from falling back into using local mutable state, functions with side-effects on global variables, and destructive functions. Combined with the single-thread design, that’s fine. You can’t avoid state all of the time, and I don’t go out of my way to be strictly functional. That’s how most other languages are designed. Hell, the Common Lisp standard even offers a whole slew of functions that are destructive for the sake of efficiency!
I’m only really getting at the fact that even the ultra-flexible of Common Lisp wasn’t written to handle all computing scenarios.
Some languages have support for neat automatic threading features: Haskell has extensions where type annotations can allow automatic parallelization, and you can use OpenMP in C++ for automatic parallel processing. For those wondering, Erlang is somewhere on my list of languages to take a look at, but it has to wait its turn! I’m still having too much fun with Lisps.
Axiomization and Language Design
Love him or hate him, Paul Graham has written quite a bit about the design of Arc. I’m not going to talk about it directly, but I will borrow his idea of reaxiomizing the core of a language as a means of producing better code on top of it. He mentions axioms as neither primitives nor library functions, but I will consider primitives as well.
I’ve talked about this a little in the past. For instance, I’ve made the case for operator overloading in Java. It was explicitly verboten in Java, as decreed by the designers. In fact, written in an early Java whitepaper titled “The Java Language Environment“,
2.2.7 No More Operator Overloading
There are no means provided by which programmers can overload the standard arithmetic operators. Once again, the effects of operator overloading can be just as easily achieved by declaring a class, appropriate instance variables, and appropriate methods to manipulate those variables. Eliminating operator overloading leads to great simplification of code.
By the letter of their assertions, they were correct. A lot of programmers would never need operator overloading to produce good code. In fact, if you’re using it just for the sake of expressiveness, you’re going to produce an unintuitive hodgepodge most of the time. However, a small but powerful minority – particularly those who do mathematical work for a living – would absolutely benefit from being able to write inline operators. I mean honestly, have you ever tried to use a BigInteger to implement something more complicated than RSA? The best that will happen is that it will end up… verbose.
Essentially, leaving out operator overloading forced Java to be more verbose and/or less readable than it needed to be. Leaving it in as an ‘axiom’ could measurably produce more compact, readable code for programmers who used it judiciously.
As an aside for those who think I’m just trolling Java, there is definitely a great Java feature for each one that misses the mark. For instance, the enums in Java follow the idea to its logical conclusion.
If you’ve been incensed by my Java discussion or are otherwise unsure that axiomization could lead to a better language, let’s look back at Lisp. Lisp changes quite a bit if you remove utility functions like reduce: it would break a lot of the compactness of the language and ruin some otherwise good functional programming. Now, it doesn’t support operator overloading, per se, but there’s nothing stopping you from changing the language to support it.
Where the Hell is All of This Going?
Back to Clojure! Clojure is based on a much different set of axioms than many of the popular languages. At its core, we see support for thread-safe data structures whose data are immutable and persistent. These were written in as axioms to the language, and you can make some good predictions for the language, assuming people stick with it.
The biggest one is that as libraries are converted to Clojure or abstract away their Java API, Clojure will develop a large set of libraries that could be given a thread-safe guarantee. For my day job, I work in a C++ shop that uses a bunch of C libraries, and we need to constantly be aware of whether or not our base libraries are thread-safe. My workplace recently developed a non-Clapack fork of our linear algebra abstraction for this reason: using libraries that aren’t designed to be threadsafe in a multithreaded environment builds bombs.
I’m too young to get a sense of what the next 10 years of programming languages might look like – but if you pressed me, it would look a lot like it does today, and we wouldn’t be better off for it. The languages that are currently in the design phase are slowly adding quite a bit of features while remaining mostly the same: for instance, C++ is getting a makeover that includes concepts, lambdas, futures, and a multithreading primitive. I’ve known C++ for over half of my life (holy shit!), and a lot of the features are sorely needed. However, it’ll be an incremental improvement at the cost of obscure compiler bugs and increased complexity.
These aren’t easy problems: for instance, if you didn’t care a lick about any external concerns like backwards compatibility and wanted to change C++ to support lambdas, how could you without just tacking it on? However, we have new languages that can pick up where the old languages left off, and continuing Fred Brooks’ prediction, there will be no silver bullet, only incremental improvements. Languages like Clojure are a step in the right direction as far as testing new computing ideas.
Popularity: 15% [?]
Available formats: [.txt] [.pdf] [.mp3]
So What’s It About?
“Underground” by Suelette Dreyfus is a great historical fiction narrative detailing the rise and fall of some crackers and phreakers and their opponents: phone company employees, system administrators, and Feds. It takes place between 1988 and 1994, when multi-user BBSes were starting to pop up and a telephone call was the ONLY way to access other computers. It’s about 99 times better than this review. In fact, I request that you stop reading this immediately and just read it yourself. It’s really that good.
That being said, most of the stories are told from the perspective of the attackers, except for a few spurious tales of BBS operators and virus attacks. All of the attacker stories have similar plot themes:
- Personal Background: Who were their friends? How was their family life?
- The first taste: How did they get into the scene? Who were their friends and mentors? How did they get free international calling? Were they chasing a white whale, or were they just enjoying themselves?
- The glory days: Usually describes a list of big fish that the attacker accessed, as well as the social support the attacker got in his home community. At this point, the Feds notice the attacker and start playing cat-and-mouse with him.
- The Law Won: The Feds make an identification, and either the attacker goes on the lam or gets busted at his computer. Nobody who got away would be at liberty to contribute to the book, so logically the attackers mentioned in the book are all caught. The court cases are described, as well as public reaction.
- Where they are today: How the legal system treated them, what they did after their legal troubles were over, and are they currently employed?
Literary Freeware
The author, Suelette Dreyfus released the book as “Literary Freeware,” allowing anyone with an internet connection to download the book for free. The text of the book was released to Project Gutenberg, and the author herself wrote a special forward for the free version of the book, describing the reasons a book’s author might decide NOT to get paid for the book:
From the forward:
Because part of the joy of creating a piece of art is in knowing that many people can – and are – enjoying it. Particularly people who can’t otherwise afford to pay $11 USD for a book. People such as cash strapped hackers. This book is about them, their lives and obsessions. It rubs clear a small circle in the frosted glass so the reader can peer into that hazy world. ‘Underground’ belongs on the Net, in their ephemeral landscape.
[...]
By releasing this book for free on the Net, I’m hoping more people will not only enjoy the story of how the international computer underground rose to power, but also make the journey into the minds of hackers involved. When I first began sketching out the book’s structure, I decided to go with depth. I wanted the reader to think, `NOW I understand, because I too was there.’ I hope those words will enter your thoughts as you read this electronic book.
The book’s website also hosted dozens of different formats/languages of the book. However, don’t try to go there anymore! It’s been taken over by some crappy hacker book e-commerce website. A reader named Rory Gordon searched the internet much more thoroughly than I did and discovered that http://www.underground-book.net is apparently the website’s actual address. Also the Wayback Machine has you covered! It even archived the 26 language/file format combinations the author made available.
How Was It?
It is good. How good? I dislike reading e-books. I like to read on my bed and sometimes write on my copy of the book. By the time I drag my desktop computer over to my bed and plug it in, I’m no longer in the mood for reading, and when I draw on the monitor, I can’t use it for other things. I actually ordered a hard copy of A New Kind of Science — review coming, whenever I summon the courage to read the last two chapters — so that I didn’t have to print out 1000 pages or read it on my computer monitor.
Despite all of this, I read the whole PDF (~300 pages) within 48 hours when I first got my hands on it — summer of 2007, for those keeping track. I stayed up late, I snuck peeks in my school IT job, and I couldn’t put it down to save my life.
At times, the pace is a lot like The Da Vinci Code, but with much longer chapters. If you don’t like that, the pacing is a lot like Harry Potter. If you don’t like that, the pacing is similar to the action sequences of Snow Crash. If you don’t like any of them, then I feel you need a good hug and some cake.
Highlights
First and foremost, it is well-written from a technical standpoint. There aren’t any “Law and Order” moments where images are super enhanced and Visual Basic GUIs are prototyped to track IP addresses. The author accessibly writes like she knows Unix systems, which is refreshing, given the number of errors I find in technical articles written by non-techies.
As for content, the story of Par is by far the best out of all of them. On a tip, he found a computer that was almost literally a gold mine: dialing it at certain times of the day caused it to spit out a large list of valid credit card numbers owned by rich Saudis. He ends up handing them out and using them like they’re free candy, which ends up drawing the eye of the Secret Service. He ends up having to go on the lam, surviving on the kindness of fellow hackers — and his 23-year-old Swiss girlfriend, Theorem. What follows is a great description of the techniques the Secret Service used to track him down (involving agencies working together on a few different continents), as well as his dumb luck in evading capture for so long.
Also, the book is chalk-full of moments like this:
If, however, the line did not have a trace on it, the company’s modem would search for its lost connection to the hacker’s modem. Without the continuous flow of electronic signals, the NorTel modem would hang up after a few seconds. If no-one reactivated the line at the NorTel end, the connection would time-out 90 seconds later and the telephone exchange would disconnect the call completely.
Mendax listened anxiously as the NorTel modem searched for his modem by squealing high-pitched noises into the telephone line. No modem here. Go on, hang up.
Suddenly, silence.
OK, thought Mendax. Just 90 seconds to go. Just wait here for a minute and a half. Just hope the exchange times out. Just pray there’s no trace.
Then someone picked up the telephone at the NorTel end. Mendax started. He heard several voices, male and female, in the background. Jesus. What were these NorTel people on about? Mendax was so quiet he almost stopped breathing. There was silence at the receivers on both ends of that telephone line. It was a tense waiting game. Mendax heard his heart racing.
A good hacker has nerves of steel. He could stare down the toughest, stony-faced poker player. Most importantly, he never panics. He never just hangs up in a flurry of fear.
Then someone in the NorTel office–a woman–said out loud in a confused voice, ‘There’s nothing there. There’s nothing there at all.’
She hung up.
Mendax waited. He still would not hang up until he was sure there was no trace. Ninety seconds passed before the phone timed out. The fast beeping of a timed-out telephone connection never sounded so good. Mendax sat frozen at his desk as his mind replayed the events of the past half hour again and again. No more NorTel. Way too dangerous.
In Conclusion
Read the book! This whole paragraph is a big link to the PDF. Just read it! It’s good!
Popularity: 20% [?]
I believe that everyone hates the feeling of starting from scratch, regardless of age or experience. This will cause people who should know better to make bad decisions, even misleading people who are conscious of the effect.
In my mental model of knowledge, I split skills between three major mastery levels:
- Those we can use professionally. I program professionally, and I practice daily to strive for mastery. I’m getting to the point where I can handle any task that is thrown at me.
- Those we can use. I can cook without killing myself of burning down my apartment complex, even though I can’t make many types of food and wouldn’t recognize a Mother Sauce if it was poured down my shirt.
- Those we couldn’t really use if our life depended on it. I’m not good at drawing. I’ve never spent time on it, and I have no motivation to learn. I can “draw” diagrams and get my point across, and this is enough for me.
All people treat the skills from the first category differently than the other two: we use them with confidence. Some people use them with arrogance. We know these fields well enough to absorb innovations and new ways of thinking. We can confidently discuss them with other people.
In my mental model, starting from scratch in our expert area causes people to reject a change. For instance: an Excel or Word guru would never willingly switch to a completely unrelated product. Relearning things line inserting line-breaks and adding pictures to a text document is completely orthogonal to anything they actually have to do on the job, much less something more complicated like Mail Merge. Instead of using it like it should be used, they would likely try using it like they used their old product, declare that it can’t ramrod the flimjam, and switch back to their old way of doing things, regardless of which is really better.
Interfaces and APIs
Altered interfaces are difficult for the end user. This isn’t just about GUIs or the placement of buttons in a menu; this extends to software APIs as well.
An altered menu causes all users to waste time looking for new ways to do something they could do 5 minutes ago. Changes to an API cause the programmers relearn a library they already knew — not to mention the laundry list of changes that need to happen to the new stuff!
APIs and Interfaces
The interface for a library or class develops massive unavoidable dependencies with use. I’ve called this “code inertia” in the past. Joel and Jeff’s recent discussion of dependencies between unit tests and code is a perfect example of code inertia: making nontrivial changes to an application can force a nontrivial number of changes to your automated testing environment.
This has not only a physical effect on the code, but also a mental effect for programmers! I’ve actually heard arguments from programmers based on the IDEA of possible future change: we shouldn’t use this library because it’s changed significantly in the past, and it might change again! Having to relearn the API combined with the frustration of updating broken code leaves a giant red flag in a programmer’s mind, even though any codebase that is being properly maintained will go through interface changes as new versions are released.
Excel
I was fortunate enough to take a Numerical Methods and Analysis class during my senior year of college.
If you’re not familiar, it’s the mathematics of computation: finding efficient approximations, determining rate of convergence, and knowing the margin of error at each stage.
This was my only college class where a calculator was ever useful. Most of our homework involved finding the values and error in iterative processes, so the professor suggested a “complex math package” for our homework: Excel.
Despite my initial skepticism, Excel is AWESOME with iterative numerical computation: type in a relative formula, highlight 50 rows, and click “fill down.” Voila! You can put a bunch of results in adjacent columns and compare convergence rates visually before you even prove that it converges at a certain rate. It’s quick, it’s interactive, and it supports easy experimentation.
Why is this relevant? My college upgraded to the Microsoft Office 2007 suite the previous summer, toolstrip and all. Every single class was punctuated by my professor loudly complaining that she HATED the new Excel because the interface was WORSE and she couldn’t find anything.
Even though she knew where everything was after 2 weeks of use, we got the same complaint every week. She had already made up her mind: it was worse.
KDE and Linus
A few years ago, Linus Torvalds publicly announced his Linux desktop preference on the GNOME message boards:
I personally just encourage people to switch to KDE.
This “users are idiots, and are confused by functionality” mentality of Gnome is a disease. If you think your users are idiots, only idiots will use it. I don’t use Gnome, because in striving to be simple, it has long since reached the point where it simply doesn’t do what I need it to do.
Please, just tell people to use KDE.
Linus
The different camps typed their representative emoticons —
and D: — and then life continued as normal. However, Linus was eventually forced to switch when the next version of KDE changed too much:
Interviewer: Another open source project that underwent a big change was KDE with version 4.0. They released a lot of fundamental architectural changes with 4.0 and it received some negative reviews. As a KDE user how has this impacted you?
Linus: I used to be a KDE user. I thought KDE 4.0 was such a disaster I switched to GNOME. I hate the fact that my right button doesn’t do what I want it to do. But the whole “break everything” model is painful for users and they can choose to use something else.
I realise the reason for the 4.0 release, but I think they did it badly. They did so may[sic] changes it was a half-baked release. It may turn out to be the right decision in the end and I will re-try KDE, but I suspect I’m not the only person they lost.
I got the update through Fedora and there was a mismatch from KDE 3 to KDE 4.0. The desktop was not as functional and it was just a bad experience for me. I’ll revisit it when I reinstall the next machine which tends to be every six to eight months.
The GNOME people are talking about doing major surgery so it could also go the other way.
Linus realizes that it might be the right decision in the long run, but there’s no escaping the fact that even the big guns in the field can’t spend his time relearning the basics every day, even if it’s the right thing to do. He has a mental model of how the desktop is supposed to work, and when KDE broke it, he fixed the problem.
Adult Learning and Malcolm Knowles
To me, a lot of the principles of API and interface design fall under adult learning. To state the obvious, most of the indended clients for interfaces are adults. We’d like them to learn how to use our products with the minimal amount of fuss.
However, if your interface is exactly like every other interface, there would be no reason to use it. You’re trying to solve a problem for yourself, and you’re trying to solve a problem for your intended users. Your users will have to learn how to solve their problems with your interface, and it had better be easy.
Enter the research of Malcolm Knowles. He is one of the big-shots in the field of adult learning, having done a lot of the early theoretical work. This site has a good description of his life’s work with researching, for the interested.
In particular, Knowles attempted to find the theory of what caused adults to best learn. Believe it or not, there hadn’t been extensive research in the field before he started. The closest that he was able to come was his theory of informal learning, through group sessions or other kinds of informal meetings. He also developed his assumptions by which adults learn:
Malcolm Knowle’s Assumptions on Adult Learning
- Self-concept: As a person matures his self concept moves from one of being a dependent personality toward one of being a self-directed human being.
- Experience: As a person matures he accumulates a growing reservoir of experience that becomes an increasing resource for learning.
- Readiness to learn. As a person matures his readiness to learn becomes oriented increasingly to the developmental tasks of his social roles.
- Orientation to learning. As a person matures his time perspective changes from one of postponed application of knowledge to immediacy of application, and accordingly his orientation toward learning shifts from one of subject-centeredness to one of problem centredness.
- Motivation to learn: As a person matures the motivation to learn is internal.
The salient bullet point is #2: experience. It’s directly listed as a basis for adult learning. I’m not saying that this is a direct proof of my mental model of knowledge, because quite honestly it’s just not a proper conclusion. However, designers of APIs and GUIs should take this as an indication that experience is something to build on, not disregard.
To use an aforementioned example, I really like the ribbon interface in Office 2007! I was proficient after only a few hours, and I enjoyed using fewer keystrokes to achieve my goals. I thought that it mapped pretty well to the old menu-based methods, and it was pretty obvious when it didn’t. If I could use only keyboard shortcuts to navigate, it would be the ideal control.
However, it’s probably a bad idea releasing it in the same year as Vista, which already scrambled some menus, changed some positions, altered some interfaces, renamed some popular folders, added UAC, etc. It all added up to too much of a change: when people sat down at it for the first time, nobody couldn’t use the darned thing.
Live and learn!
Footnote
I remember a minor fuss when Linux 2.6.0 came out because the device driver interface changed. Linus himself descended from the cloud to state that he makes the right design choices for Linux without regard to compatibility issues. It was going to tie in really nicely with my point, and my Google Fu has failed me. up. The device driver interface changed from 2.4 to 2.6, and that there was a of device driver complaints. At this point, I just want to know if I was making this up.
Popularity: 15% [?]