Saturday, January 4, 2025

A Newbie Is Exposed to Common Lisp

At ChangeSafe our product was written in Common Lisp. But for "black box" testing, we didn't need the test code to be written in Common Lisp. In fact, we wanted the test code to be written in an unrelated language so that we could be sure that the product's API was language neutral.

Skill in Common Lisp was simply not a requirement — not even relevant — for QA jobs. We were a startup company, so the initial hires for QA would set the culture for the department. We were looking for people who had initiative, were self-motivated, could work with vague and underspecified guidance, figure out the job that needed to be done, and then do it. We found a young guy named Eric who fit the bill.

Eric set up our QA efforts and wrote the initial black box test code for the product. In his spare time, off the clock, he got curious about Common Lisp and why we chose to develop the product using it. He had never heard of the language. He decided to pick up the Common Lisp specification and teach himself the language. I told him that it was unnecessary for the job, but I didn't discourage him from broadening his horizons.

Eric came to me early on and asked me to explain some details about Common Lisp. He had just learned about lambda expressions and was trying them out with mapcar and other higher-order functions. It was obvious to him that a lambda expression was capturing the local stack variables. When the lambda was passed downwards to mapcar, it was able to access the variables from its point of origin further up the stack. He could see the potential, and thought it was an interesting feature.

Then, just to see what would happen, he returned a lambda expression up the stack. To his suprise, it still worked, even though the stack frame was no longer there. He had three questions for me the next day: Was this intentional? How did it work? And why would anyone do this?

I assured him that it was intentional. The feature worked by the compiler generating code to move the captured variables off of the stack and into the heap. The designers of Lisp wanted lambda expressions to “just work”, regardless of how you passed them around. The correct engineering decision — the “right thing” — was to place the burden of making this happen on the language implementor, not on the user of lambda expressions.

I told him that the reason we used Common Lisp was because the designers of the language placed a high value on doing thing “the right way”. Things were carefully designed to be easy to use and to work correctly, even in the corner cases. It was recognized that this would make it more difficult to implement the language, but a lot easier to program in it.

Eric was, quite frankly, impressed by this. It was clear to him that the designers of Lisp were in a league of their own. He couldn't wait to learn more about the language.

Incidentaly, Eric wasn't the least bit put off by the paretheses. He considered them to be a quirk that was ideomatic of the language. Some languages use infix notation, some calculators use postfix. Lisp happened to use prefix notation. It was no big deal.

Eric was a great hire and had the potential to go far had the company not gone under when the internet bubble burst.

No comments: