teaching machines

CS 330: Lecture 39 – Exit(0)

Dear students,

Today we close out our formal exploration of the stuff of programming languages. This is what we said we’d look into in the syllabus:

  • Recognize and exploit the strengths of three major programming paradigms: imperative, functional, and object-oriented.
  • Reason about the strengths and weaknesses of various type systems.
  • Weigh the costs and benefits of static and dynamic decision making.
  • Develop code in languages with addressable and dynamically-allocated memory.
  • Design and develop tools for recognizing and interpreting domain-specific languages.

At the very beginning of the semester, we investigated regular expressions as a language for expressing languages. We built a lexer and parser for a language that didn’t exist before. We got a taste for what an interpreter does to execute our code. We saw that a small language that caters to the application domain can make expressing ideas simpler than a general purpose language.

From there we entered into a discussion of types, a feature that is missing from the machine code layer underneath all our abstractions. C uses types to make our code a little safer, but it doesn’t stray far from the metal. C++ said that the user should be able to develop new types too, through classes. With so many types lying around, we discussed a need to make our code work with multiple types through the various forms of polymorphism. We looked into C++’s inheritance and template system.

From there we entered the world of functional programming through the lens of Haskell. We spent a lot of time on this language because it had a lot of new ideas. We passed functions around, we used pattern matching to destructure compound structures, we supplied only a subset of a function’s parameters to get back a function awaiting the remainder. We encountered the idea of function literals or lambdas. We saw how the functional patterns of map, filter, and fold underpin a great many of algorithms, and we took those ideas to other languages like Java and Ruby.

We saw the in most languages, lambdas form a closure, capturing the variables that are in scope at the time they are defined. These closing semantics make it such that our callbacks can be parameterized without parameters.

Then we visited parameter-passing strategies, and we discovered that not every language is pass-by-copy. The pass-by-closure and pass-by-jit strategies have merit. Their laziness lets us do some crazy things, like write our own control structures and delay expensive and perhaps infinite computations until the time of need.

Finally, we got into the world of metaprogramming, in which our programs are aware of themselves.

We talked about a lot of stuff. Our goal was never for you to memorize anything or learn the minutiae of ten different programming languages. Rather, my feelings about why this class is important can be summarized in two questions.

First, we often refer to the stuff we developers use as tools. Part of me really likes this word. My father was a mechanic, and he had an addiction to tools. They gave him leverage and torque, they made it possible to get work done in very narrow spaces, and they wiped clean at the end of job, almost always outliving one job to serve another tomorrow. But I also don’t like this word to describing programming languages.

Is a spider’s web a tool? When I think of tools, I think of something external to the tool user. But a spider’s web comes from its abdomen. It is something internal made external. In this sense, it is much more than a tool. I feel the same way about language in general. Our brains have this uncanny facility for recognizing and generating language. Grammars and encodings seem to naturally flow out of our brains to help us communicate. A programming language is not some external force acting upon us. It comes from us, it is us, and it shapes what we can do. It is my hope that the tools that you encounter in your lives embed themselves inside you and give the ideas that are inside of you a voice. If the right programming language doesn’t exist, you have what it takes to make your own. I hope you can teach those ideas to a machine, and share them with others.

Second, I want to discuss a little bit of psychology. I think what happens to our brains as we grow is described well by psychologist William Perry. He studied college students like you in the 1950s and 1960s and found distinct patterns to their cognitive development. Let’s summarize the main stages:

  1. Dualism: I believe actions and beliefs are either right or wrong, and these labels are designated by an Authority that I can can trust. I shut my eyes and ears to whatever and whomever is wrong. Wrong things should be burned, and wrong people deserve punishment. Example: My iPhone is a masterpiece of design and engineering, delivered to Earth by the almighty Apple. Android only exists because Google found enough monkeys that something had to emerge.
  2. Multiplicity: I am an Authority, and so are you. Right and wrong are a matter of opinion, and if you listen to others you’re a sheep. I’m going to do what I think is right, and you can do your thing. Anyone that says otherwise is an unenlightened dualist. Example: A phone is a phone. I had to steal this iPhone, but they were overpriced and I had just spent the last of my paycheck on Steam’s Winter Sale.
  3. Relativism: I am not the Authority I thought I was, and you aren’t either. It turns out that some Authorities are charlatans and hypocrites. Some are right about area X but have it all wrong in area Y. Example: iPhones are great for people who want stuff that works out of the box. But man, Android phones are great for somebody who wants to tinker.
  4. Commitment: Based on what I’ve seen of the world, I trust much of what Authorities A and B have to say. But I will keep evaluating new Authorities that come along, and carefully weigh what they have to say. Example: I like my iPhone. Those new devices from Samsung have some awesome features, though. I hope Apple copies them soon and there’s no lawsuit.

In the world of technology, there is absolutely no reason to monogamously marry a programming language or a platform. There’s no need to choose. Your employer can get you an iPhone and an Android phone. You can use Windows, Mac, and Linux, either with virtual machines or dual booting. You can and should know many languages, and continue learning new ones, because the world of technology is a world where isRight is neither true nor false. It is null, waiting to be defined. Your world will shift underneath you, but you can save yourself some trouble by shifting it yourself. You must be prepared to update yourself, and that can’t happen if Java or C or Ruby or Javascript are the one true way. You don’t have to love all your choices, but by knowing them, you can achieve what many critics do not: informed dissent.

In which of Perry’s stages of cognitive development are you? The early stages have us believing that the world is full of accurately labeled things, each marked good or bad. The middle stages have us believing that those labels were placed at random, and we reject the very idea of good and bad. We don’t realize our own hypocrisy in that we are labeling labels as bad. The final stages have us accepting that our world is full of mixed bags, that some things are better than others, and that both good and bad things can be made better. This situation is extremely relevant to our discipline, in which people are eager to sell their soul to a particular technology. It’s kind of like sports. You invest your identity in something in which you have no participation. Your future workplaces may be very happy to let you become an expert at one particular good thing, but you will calcify and obsolesce with that technology.

Let me tell you the story of two swordsmiths of Japan—courtesy of Wikipedia:

A legend tells of a test where Muramasa challenged his master, Masamune, to see who could make a finer sword. They both worked tirelessly and eventually, when both swords were finished, they decided to test the results. The contest was for each to suspend the blades in a small creek with the cutting edge facing the current. Muramasa’s sword, the Juuchi Yosamu (“10,000 Cold Nights”) cut everything that passed its way; fish, leaves floating down the river, the very air which blew on it. Highly impressed with his pupil’s work, Masamune lowered his sword, the Yawarakai-Te (“Tender Hands”), into the current and waited patiently. Only leaves were cut. However, the fish swam right up to it, and the air hissed as it gently blew by the blade. After a while, Muramasa began to scoff at his master for his apparent lack of skill in the making of his sword. Smiling to himself, Masamune pulled up his sword, dried it, and sheathed it. All the while, Muramasa was heckling him for his sword’s inability to cut anything. A monk, who had been watching the whole ordeal, walked over and bowed low to the two sword masters. He then began to explain what he had seen.

“The first of the swords was by all accounts a fine sword, however it is a blood thirsty, evil blade, as it does not discriminate as to who or what it will cut. It may just as well be cutting down butterflies as severing heads. The second was by far the finer of the two, as it does not needlessly cut that which is innocent and undeserving.”

Thus we come to the final haiku of the semester:

Which sword is better?
The unchecked one or the checked?
Well, I’ve got two hands

Here’s your TODO:

  • Complete your takehome final exam. I ask that you test all code that you write. Haphazard answers that do not appear to be tested will not receive credit. Slide your exam under my office door before 3 PM on Friday, May 18. Tests received after this time will not be graded. Electronic submissions are not accepted.

There’s no next time!

Sincerely,

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *