I've been enjoying teaching Intelligent Systems again this semester. A big part of the fun is re-reading old papers. I had a lot of fun re-reading and thinking about the ideas in William Clancey's classic paper, Heuristic Classification. Long-time readers may recall me mentioning this paper in a long-ago post about one of computing's basic concepts, the unity of data and program.
My students didn't read this paper, but they did read a chapter from Peter Jackson's Introduction to Expert Systems that discusses it in some detail. The chapter is called "Heuristic Classification", too, but it's really about much more: the distinction between tasks and methods, the distinction between analytic tasks and synthesis tasks, and Clancey's heuristic classification method itself.
This one paper set me off on a mini-lecture that could have been much longer. To me, it felt like a technical reminiscence, a story of ideas that set the stage for my own work on design patterns of knowledge-based systems. Eventually, I had to cut my story short, both in the interest of having time to do other things in class that day and in the interest of not boring students with my own deep fascination with these topics. I hope I said enough to give them a sense of how important these ideas are and to whet the appetite of any student who might have his or her own fascination with the ideas.
Our reading and our conversation that day brought to my mind a rich set of ideas for students of intelligent systems to think about, such as:
Many of these go beyond my current interests precisely because they are at the beginning of their studies, focused on building a particular system. They may find their interest in these ideas piqued after they build one of these systems, or three, and realize just how many degrees of freedom they face when writing a program that behaves "intelligently".
The latest newsletter from my graduate alma mater mentioned that one of my favorite profs is retiring. I always considered myself fortunate to have studied AI with him in my first term of grad school and later to have worked as a TA with him when he taught the department's intro course. I learned a lot from both experiences. The AI course taught me a lot about how to be a scientist. The intro course taught me a lot about how to be a teacher.
I often hear about how faculty at research schools care only about their research and therefore make for bad teachers in the undergraduate classroom. There are certainly instances of this stereotype, but I think it is not generally true. Active researchers can be bad teachers, but then again so can faculty who aren't active in research. Working as this prof's TA, I saw that even good researchers can be very good undergraduate teachers. He cared about his students, cared about their learning, and prepared his classes carefully. Those are important ingredients for good teaching no matter who is doing it.
I dropped him a quick e-mail to thank him for all his guidance while I was in grad school and to wish him well in retirement. In his response, he expressed a sentiment many teachers will recognize:
I'm sure you have been in the university business long enough to realize what a great job we have. Working with students such as you has been very rewarding.
I have, indeed, been in the university business long enough to realize what a great job we professors have. Over the years, I've had the good fortune to work with some amazing students, both undergrad and grad. That joy comes as part of working with a lot of wonderful young people along their path to professional careers and meaningful lives.
When you add the opportunity to work with students and the opportunity to explore interesting ideas and follow where they might lead us, you get a nearly unbeatable combination. It's good for me to step back every once in a while and remember that.
One of my students has been learning Haskell as a prelude to exploring purely functional data structures. Recently, he wrote a short blog entry describing some of the ideas he has found most exciting. It ended with a couple of code snippets showing the elegance and brevity of list comprehensions compared to what he was used to in imperative languages. The student apologized for his imperative example, because he wrote it in Java using objects. In his mind, that made it object-oriented, not imperative.
This is a common misconception. Most OOP is imperative. Objects have state that changes.
Of course, one can write object-oriented code in a functional style by emphasizing return values and by creating new objects instead of changing existing objects. Certain kinds of objects, such as money, should probably be implemented as value objects without modifiable state. But most OO practice and intent is stateful, hence imperative.
I've read many a blog entry over the last few years in which OO gurus extol functional OO as a way to write better code. I think we can overdo it, though. Whenever I take this idea too far, though, I soon find myself contorting the code in a way that seems to serve the idea but not the program I am writing. Still, sometimes it can be fun to turn the knob on the functional OO dial up to 10 and try to write purely functional OO code, with no side effects of any sort. This kind of programming challenge has always appealed to me. It can teach you a lot about the strengths and limits of the tools you use.
It occurs to me that one way to enforce the rules of the functional OO challenge would be to turn off the imperative features in my language. That can be tough to do in a language with libraries full of stateful objects. But simply turning off the assignment operator in a language such as Java would make many of us struggle to write even simple programs.
Actually, I had the idea of turning off assignment statements late in a long conversation I had with myself while thinking about my student's comment and my response to him. If most OO is imperative, I wonder what it would be like to write "purely imperative" OO code. This would mean creating objects that never returned a value in response to a message. In a sense, these objects would be pure state and action, at least from the perspective of other objects in the system.
At first, this idea seemed absurd. What value could come from it?
This stylistic challenge is quite easy to enforce, either in practice or in tools: simply require all methods to be void. Voilé! No return statements are allowed. No values can be passed from one object to another in response to a message. An object would affect the state of the program either by modifying its own state or by sending a state-changing message to another object, perhaps an argument that it received along with a message.
Talk about Tell, Don't Ask! In this style of programming, I can only tell objects to do things. I can't ask for any data in return.
So, perhaps some value could come from this little challenge after all. I would have to take Tell, Don't Ask -- and encapsulation -- seriously. Programming in this way can help us see just how much we can accomplish with truly independent objects, providers of services who encapsulate their state and take full responsibility for its management. I think that, in many respects, this idea is faithful to the original idea of objects and OOP -- perhaps more faithful than our current incarnation of them in languages with functions.
I think that this could also help us in another way. Functional programming offers us one path to increased parallelism by eliminating state changes and thus making each computation independent of global context. Purely imperative programming offers another path, one that fits the early OO vision of encapsulated agents interacting via message passing. This is similar to the actor model that we see these days in languages such as Scala and Erlang. Of course, this model goes back to the work of Carl Hewitt, which inspired the evolution of both Scheme and Smalltalk!
I have not thought through all the implications of my thought experiment yet. Maybe it's nonsense; maybe it's a solved problem. Still, I think it might be fun to turn the dial up to 10 on stateful programming and try to implement a non-trivial program with no return statements. How far could I go before things got uncomfortable? How far could I go before I found myself contorting the code in a way that serves the idea more than the program I was writing?
Sometimes I am surprised just how many interesting thoughts can fall out of the simplest conversations. Too bad time to play with them doesn't fall out, too.
It's been a good start to semester, though too busy to write much.
My Intelligent Systems course shows promise, with four teams of students taking on some interesting projects: recognizing faces, recognizing sign language, classifying transactions in a big-data finance context, and a traditional knowledge-based system to do planning. I am supervising a heavier-than-usual set of six individual research projects, including a grad student working on progressive chess and undergrads working on projects such as a Photoshop-to-HTML translator, an interpreter for a homoiconic OO language, and pure functional data structures. This all means that I have a lot to learn this semester!
I'm also still thinking about the future, as the dean's 3-year review of my work as department head proceeds. Yesterday I watched the video of Steve Jobs's commencement address at Stanford. This time around, his story about the freeing power of death grabbed special attention. Jobs gets up each day and asks himself, "If this is your last day on Earth, will you be happy doing what you are doing today?" If the answer is "no" too many days in a row, then he knows he needs to make a change.
That's a bracing form daily ritual. When it comes to this level of self-honesty, on most days I feel more like Howard W. Campbell, Jr. than Steve Jobs. I think I also finally grok this aphorism, a favorite saying of a friend: "Real men don't accept tenure". It can be an unhealthy form of academic immortality.
The question I ask myself more often than not these days is, "Are you programming?" Let me substitute "programming" for "writing" in a passage by Norman Fischer quoted at What I've Learned So Far:
... programming is a sort of absolute bottom line. "Are you programming?" If the answer is yes, then no matter what else is going on, your life -- and all of life -- is basically OK. You are who you are supposed to be, and your existence makes sense. If the answer is no, then you are not doing well, your relationships and basic well-being are in jeopardy, and the rest of the world is dark and problematic.
A day without writing code is like, you know, night. (With apologies to Steve Martin.)
When you run a road race, you usually receive some token, usually a ribbon or a medal. The longer the race, the more likely you are to receive a medal, but even shorter distances these days often come with a medal. For marathons and half-marathons, the race medal is often a Very Big Deal, both for race sponsors and the runners.
Here is an example, from the 2004 Des Moines Marathon:
Local color plus attitude -- this is a great design!
For many runners, the race medal is an important memento. I appreciate this feeling and understand the desire to keep and display the symbol of their achievement. This feeling is perhaps strongest in first-time and one-time marathoners, who rightly see their race as the culmination of a much longer journey.
After a while, though, these mementos begin to pile up. I have run seven marathons, many half-marathons, and many more shorter races, and the result was a box full of ribbons, medals, and medallions. Over the last year or so, I have been working to reduce clutter in my house and mind, which has led me to ask myself some tough questions about the role of keepsakes. In the grand scheme of things, a shoebox of race medals is no big deal, but it was really just one manifestation of my habit of stockpiling memories: ticket stubs; programs from plays, recitals, and school programs; newspaper and magazine clippings; and, yes, race memorabilia. The list goes on. I wanted to make a change: to keep fewer physical keepsakes and to work harder to preserve the memories themselves.
Could I really give up my race medals? If so, could I just throw them away?
Walking around the race expo for the 2010 Des Moines Marathon, I discovered a better way. There I learned that about Medals4Mettle, a non-profit founded in my hometown of Indianapolis that collects marathon finisher's medals and distributes them to people who have "demonstrated similar mettle" by dealing with disease, handicaps, and other challenges:
As marathoners run through the streets, large crowds cheer the runners for their effort. Medals4Mettle lets these runners, healthy enough to compete in such an event, return the cheers to those who have supported them.
Why should my medals gather dust in a box in my basement when they could cheer up a child facing a real challenge? I finish these races through a combination of great luck in birth and in life. Put in context, my accomplishments are small.
The Iowa chapter of Medals4Mettle seems to be primarily the work of one man, Jason Lawry, a Des Moines runner. I was touched by his commitment, took his card, and ran my race.
Over Christmas break, I pulled the trigger and donated my medals to Jason's group. First, I snapped digital photos of every marathon and half-marathon medal in my box. Not being a great photographer or the owner of an awesome camera, this took a while, but it allowed me to spend some time saying good-bye to my medals. In the end, I showed a small bit of weakness and kept three. The 2003 Chicago Marathon was my first and so holds a special place with me:
I ran the 2009 500 Festival Mini-Marathon in my hometown after two years of unexplained illness that brought racing and most running to a halt:
Finally, there is something about running the 2007 Marine Corps Marathon that will always stick with me. Sharing the course with our nation's military, both veterans and active duty, inspired me. Receiving this medal from uniformed Marines makes it special:
Keeping three mementoes with particular significance seemed okay, though they might well mean more to someone else. Perhaps I'll donate these medals later, as memories fade or as new ones take on greater significance. I was proud to drop off the rest of them at a local runner's store for collection by Mr. Lawry.
And, no, I did not keep that cool 2004 Des Moines medal with the gangsta Grant Wood theme. I hope it brings a smile to the face of a person who can use the smile.
Every new course starts with a tingle of the unknown. How will this semester go? Will I enjoy it? Will my students? Will they learn what they want and need to learn? Will I?
No matter how many years I teach, or how well I know the students in my class, I feel the same way. I loved this as a student, too. One of then reasons I liked my universities' trimester systems was that I got to feel it three times a year, not just two.
I am completing the first week of teaching Intelligent Systems, one of my department's capstone project courses for majors. I used to teach this course every spring, but I haven't taught the course since 2002, when I went on sabbatical and let a junior colleague take on our AI sequence. Imagine my surprise to find that this area of computer science has changed some in eight years! That makes teaching the course again fun and challenging.
Students are beginning to form teams and hone in on systems to build. This group has an interesting history with me. Some I had in class last term. Some last took class with me last fall or last summer. One last took a class with in Fall 2006, when I introduced media computation to our CS1 course. A few are seeing me in class for the first time, after receiving department e-mail from me for years.
I feel some pressure teaching this course. Eight years is a long time in CS Time and in Internet Time. Change happens, and accelerates. I have to refamiliarize myself with what's state of the art. Not having taught AI over the same period, I have to refamiliarize myself with what students find interesting in AI these days. That's fun, and there's some comfort in knowing that AI has a certain evergreen appeal to young minds. Games, machine learning, and "real-world problems" always seem to interest some students.
More pressure... This is a course I prefer to teach with little or no lecture. Every day, I potentially face the question that scares most of us, at least a little bit: What will I do today? I have a general plan for the course, but I can't script it. Much of how the course proceeds depends on what the students think and do. I've been reactive so far, in what I feel is a good way. On the first day, I asked students to fill out a short survey on their background, interests, and goals for the course. On the second day, my remarks responded to what they wrote on the surveys and connected those answers with recent experiences of my own and on the sort of problems we face in computing these days. Among these is the way "big data" interacts with the time and space constraints we always face in CS.
I am excited.
My initial inclination after class was to tweet. That would have been quick and easy. Sometimes, that's the right way to go. 140 characters is perfect for a pithy observation. But I realized that my immediate observation after class was unfolding other thoughts about the week and the course, and about how I am feeling. This is one of the reasons I blog: to encourage myself to think further, to reflect more deeply, and to decide what things mean. So I blogged instead. My initial inclination for a tweet became the first line of my entry. It will also make a nice tweet announcing the blog entry!
"You are what you eat." You probably heard this bon mot as a child. It encouraged us to eat healthy foods, so that we could grow up to be big and strong.
I think the same thing is true of what we read. When we eat, we consume nutrients and vitamins. When we read, we consume ideas. Some are meat and potatoes, others fruits and vegetables. Some are the broad base of a healthy diet, like breads and grains. Others are junk food. Ideas may even occasionally be roughage!
There probably isn't an idea analogue to the food pyramid. Even more than with the food we eat, there is no right answer for what and how much of any kind of literature we should read. There are many ways for any particular person to read a healthy diet. Still, there are kinds of literature that offer us ideas in different forms, different concentrations, and different modalities. Fiction is where most children start, whether historical, fantastical, or simply about life. Non-fiction, too, comes in many categories: biography, history, science, ... too many to mention.
However, I do think that writer Matthew Kelly is right when he says, "We need a diet of the mind just as much as we need a diet of the body." Just as we should be mindful of what we put in our bodies, we should be mindful of what we put in our minds.
Each person needs to find the reading balance that makes them healthy and happy. I tend to read a lot of technical literature in my own discipline. Academics are pone to this imbalance. One of my challenges is to read enough other kinds of things to maintain a balanced intellectual life. It turns out that reading outside my discipline can make me a better computer scientist, because it gives me more kinds of ideas to use. But the real reason to read more broadly is to have a balanced mind and life.
I know people who wonder why they need to bother reading fiction at all. It doesn't make them better programmers. It doesn't help them change the world via political action. Both of these statements are so, so wrong. Shakespeare and Euripides and Kurt Vonnegut can teach us about how to change the world and even how to become better programmers! But that's not the point. They also make us better people.
Whenever I encounter this sentiment, I always send my friends to Tim O'Reilly's The Benefits of a Classical Education. Most programmers I know hold O'Reilly Media in near reverence, so perhaps they'll listen to its founder when he says, "Classical stories come often to my mind, and provide guides to action". The fiction I've read has shaped how I think about life and problems and given me ways to think about solutions and actions. That's true not only of the classics but also of Kurt Vonnegut and Isaac Asimov, Arthur Clarke and Franz Kafka.
As I wrote recently, I've been reading Pat Conroy's My Reading Life. Near the end of the book, he tells a powerful story about him and his mom reading Thomas Wolfe's Look Homeward, Angel when he was a teenager. This book gave them a way to talk about their own tortured lives in a way they could never have done without a story standing between them and the truths they lived but could not speak. As Conroy says, "Literature can do many things; sometimes it can do even the most important things." I might go one step further: sometimes, only literature can do the most important things.
Sure, there is plenty junk food for the mind, too. It is everywhere, in our books and our blogs, and on our TV and movie screens. But just as with food, we need not eliminate all sweets from our diets; we simply need to be careful about how much we consume. A few sweets are okay, maybe even necessary in some people's diets. We all have our guilty pleasures when it comes to reading. However, when my diet is dominated by junk, my mind becomes weaker. I become less healthy.
Some people mistakenly confuse medium with nutritional value. I hear people talk about blogs and Twitter as if they offer only the emptiest of empty calories, the epitome of junk reading. But the medium doesn't determine nutritional value. My Twitter feed is full of links to marvelous articles and conversation between solid thinkers about important ideas. Much is about computer science and software development, but I also learn about art, literature, human affairs, and -- in well-measured doses -- politics. My newsreader serves up wonderful articles, essays, analyses, and speculations. Sure, both come with a little sugar now and then, but that's just part of what makes it all so satisfying.
People should be more concerned when a medium that once offered nutritional value is now making us less healthy. Much of what we call "news" has in my mind gone from being a member of the grain food group to being junk food.
We have to be careful to consume only the best sources of ideas, at least most of the time, or risk wasting our minds. And when we waste our minds, we waste our gifts.
You are what you read. You become the stories you listen to. Be mindful of the diet of ideas you feed your mind.
While grading last month, one of my colleagues sent me a note:
A student handed in the last assembly language assignment. It was very well done. Very professional.
One tiny problem: it was in IBM PC assembly, not the IBM mainframe assembly that I have been teaching.
I guess it's always good to be specific when you order programming online.
This was funny and sad at the same time. Much has been made in the last couple of months of paper-writing for hire, and we in CS have been talking about the problem of seeking out solutions on-line, even custom-written programs, for a while now. But we seem to be entering a new world of programming for hire. It creates pragmatic challenges for instructors on top of what is already a challenging enough task.