June 05, 2024 2:58 PM

Quick Links from Reading

I have posted or re-posted several links on Mastodon recently, after having been mostly silently for a few weeks. Whenever I end up posting a flurry of items, I find myself thinking, "I may want to use these somewhere later..." and realizing that I don't want to rely on Mastodon search to find them. So here a few, for the record (and for the pleasure of those readers who don't follow my social media postings with the tenacity they deserve).

Oneliner-izer https://github.com/csvoss/onelinerizer converts any Python 2 script into a single line of code.

Favorite line from the documentation:
"Never pass up an opportunity to use the Y combinator."

In my programming languages course, we learn how local variables are a syntactic abstraction. If nothing else, I can use this tool to demonstrate translations of simple Python code into their equivalent function applications.


This is from a short blog post on receiving an AI-generated email message from a friend:

The effort, the clumsiness, and the time invested are where humanity is stored.
-- https://mrgan.com/ai-email-from-a-friend/

Then again, I would like this. I still send actual physical cards to many friends and members of my family each year at Christmas, with (short) personalized handwritten notes. I am not always the best of friends, but occasionally I invest a little effort, clumsiness, and time in saying "I'm thinking of you."


It's surveillance wine in safety bottles.
-- https://mastodon.world/@Mer__edith/112535616774247450

I haven't studied the GDPR provision that Whitaker is commenting on, so I have no comment on it directly. But I love this phrase.


"But stay lucid, even during office hours."

That's a tough ask some days.

I was pointed in the direction of this Camus quote by a tweet from @DylanoA4. The image he posted ends with this quote, but the passage beginning with it is even more fitting as the set-up for a prof's joke about office hours. Here that is, courtesy of a post on goodreads:

But stay lucid, even during office hours. As soon as we are alone in its presence, strive after the nakedness into which the world rejects us. But above all, in order to be, never try to seem.

Every prof knows the rejection of empty office hours. "Where are all the students who need my help, or my sage advice on life and the burning topics of the day?" we cry, palms upturned. But don't count on using that time for any other task either... Students will arrive when you least expect them. Stay lucid, and strive after the nakedness into which the world rejects us.

All academics become Stoics, or spend their lives raging against the night.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

May 30, 2024 5:56 PM

In Loco Parentis

Avdi Grimm sent out an email to one of his lists this week. After describing his daily domestic tasks, which are many, he segues to professional life. I am not a software consultant, but this sounded familiar:

I telepresence into my client team, who I will sit with all day. My title might as well be "mom" here as well; 20% of my contributions leverage my software development career, and the rest of the time I am a source of gentle direction, executive function, organization, and little nudges to stay on target.

There are days when the biggest contribution I make to my students' progress consist of gentle direction and little nudges that have little to do with Racket, programming languages concepts, or compilers. Often what they need most is help staying focused on a given task. Error messages can distract them to the point that they start working on a different problem, when all they really need to do is to figure out what the message means in their specific context. Or encountering an error makes them doubt that they are on the right path, and they start looking for alternative paths, which will only take them farther from a solution.

I don't sit virtually with any students all day, but I do have a few who like to camp out in my office during office hours. They find comfort in having someone there to help them make sense of the feedback they get as they work on code. My function is one part second brain for executive function and one part emotional support. My goal as educator in these encounters is to help them build up their confidence and their thinking habits to the point that they are comfortable working on their own.

I have had colleagues in the past who thought that this kind of work is outside of the role that profs should play. I think, though, that playing this role is one way that we can reach a group of students who might not otherwise succeed in CS at the university level. Almost all of them can learn the material, and eventually they can develop the confidence and thinking habits they need to succeed independently.

So, if being dad or mom for a while helps, I am up for the attempt. I'm glad to know that industry pros like Avdi also find themselves playing this role and are willing to help their clients grow in this way.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

March 14, 2024 12:37 PM

Gene Expression

Someone sent me this image, from a slide deck they ran across somewhere:

A slide labeled 'Gene Expression'. The main image a casual shot of actor Gene Wilder, labeled 'One Gene'. There a three side images of Wilder as iconic characters he played in 'Willy Wonka & the Chocolate Factory', 'Young Frankenstein', and 'Blazing Saddles'. There are arrows from the main image to the three side images, labeled 'Many Outcomes'.

I don't know what to do with it other than to say this:

As a person named 'Eugene' and an admirer of Mr. Wilder's work, I smile every time I see it. That's a clever way to reinforce the idea of gene expression by analogy, using actors and roles.

When I teach OOP and FP, I'm always looking for simple analogies like this from the non-programming world to reinforce ideas that we are learning about in class. My OOP repertoire is pretty deep. As I teach functional programming each spring, I'm still looking for new FP analogies all the time.


Note: I don't know the original source of this image. If you know who created the slide, please let me know via email, Mastodon, or Twitter (all linked in the sidebar). I would love to credit the creator.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

February 29, 2024 3:45 PM

Finding the Torture You're Comfortable With

At some point last week, I found myself pointed to this short YouTube video of Jerry Seinfeld talking with Howard Stern about work habits. Seinfeld told Stern that he was essentially always thinking about making comedy. Whatever situation he found himself in, even with family and friends, he was thinking about how he could mine it for new material. Stern told him that sounded like torture. Jerry said, yes, it was, but...

Your blessing in life is when you find the torture you're comfortable with.

This is something I talk about with students a lot.

Sometimes it's a current student who is worried that CS isn't for them because too often the work seems hard, or boring. Shouldn't it be easy, or at least fun?

Sometimes it's a prospective student, maybe a HS student on a university visit or a college student thinking about changing their major. They worry that they haven't found an area of study that makes them happy all the time. Other people tell them, "If you love what you do, you'll never work a day in your life." Why can't I find that?

I tell them all that I love what I do -- studying, teaching, and writing about computer science -- and even so, some days feel like work.

I don't use torture as analogy the way Seinfeld does, but I certainly know what he means. Instead, I usually think of this phenomenon in terms of drudgery: all the grunt work that comes with setting up tools, and fiddling with test cases, and formatting documentation, and ... the list goes on. Sometimes we can automate one bit of drudgery, but around the corner awaits another.

And yet we persist. We have found the drudgery we are comfortable with, the grunt work we are willing to do so that we can be part of the thing it serves: creating something new, or understanding one little corner of the world better.

I experienced the disconnect between the torture I was comfortable with and the torture that drove me away during my first year in college. As I've mentioned here a few times, most recently in my post on Niklaus Wirth, from an early age I had wanted to become an architect (the kind who design houses and other buildings, not software). I spent years reading about architecture and learning about the profession. I even took two drafting courses in high school, including one in which we designed a house and did a full set of plans, with cross-sections of walls and eaves.

Then I got to college and found two things. One, I still liked architecture in the same way as I always had. Two, I most assuredly did not enjoy the kind of grunt work that architecture students had to do, nor did I relish the torture that came with not seeing a path to a solution for a thorny design problem.

That was so different from the feeling I had writing BASIC programs. I would gladly bang my head on the wall for hours to get the tiniest detail just the way I wanted it, either in the code or in the output. When the torture ended, the resulting program made all the pain worth it. Then I'd tackle a new problem, and it started again.

Many of the students I talk with don't yet know this feeling. Even so, it comforts some of them to know that they don't have to find The One Perfect Major that makes all their boredom go away.

However, a few others understand immediately. They are often the ones who learned to play a musical instrument or who ran cross country. The pianists remember all the boring finger exercises they had to do; the runners remember all the wind sprints and all the long, boring miles they ran to build their base. These students stuck with the boredom and worked through the pain because they wanted to get to the other side, where satisfaction and joy are.

Like Seinfeld, I am lucky that I found the torture I am comfortable with. It has made this life a good one. I hope everyone finds theirs.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Running, Software Development, Teaching and Learning

February 09, 2024 3:45 PM

Finding Cool Ideas to Play With

In a recent post on Computational Complexity, Bill Gasarch wrote up the solution to a fun little dice problem he had posed previously. Check it out. After showing the solution, he answered some meta-questions. I liked this one:

How did I find this question, and its answer, at random? I intentionally went to the math library, turned my cell phone off, and browsed some back issues of the journal Discrete Mathematics. I would read the table of contents and decide what article sounded interesting, read enough to see if I really wanted to read that article. I then SAT DOWN AND READ THE ARTICLES, taking some notes on them.

He points out that turning off his cell phone isn't the secret to his method.

It's allowing yourself the freedom to NOT work on a a paper for the next ... conference and just read math for FUN without thinking in terms of writing a paper.

Slack of this sort used to be one of the great attractions of the academic life. I'm not sure it is as much a part of the deal as it once was. The pace of the university seems faster these days. Many of the younger faculty I follow out in the world seem always to be hustling for the next conference acceptance or grant proposal. They seem truly joyous when an afternoon turns into a serendipitous session of debugging or reading.

Gasarch's advice is wise, if you can follow it: Set aside time to explore, and then do it.

It's not always easy fun; reading some articles is work. But that's the kind of fun many of us signed up for when we went into academia.


I haven't made enough time to explore recently, but I did get to re-read an old paper unexpectedly. A student came to me to discuss possible undergrad research projects. He had recently been noodling around, implementing his own neural network simulator. I've never been much of a neural net person, but that reminded of this paper on PushForth, a concatenative language in the spirit of Forth and Joy designed as part of an evolutionary programming project. Genetic programming has always interested me, and concatenative languages seem like a perfect fit...

I found the paper in a research folder and made time to re-read it for fun. This is not the kind of fun Gasarch is talking about, as it had potential use for a project, but I enjoyed digging into the topic again nonetheless.

The student looked at the paper and liked the idea, too, so we embarked on a little project -- not quite serendipity, but a project I hadn't planned to work on at the turn of the new year. I'll take it!

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

January 21, 2024 8:28 AM

A Few Thoughts on How Criticism Affects People

The same idea popped up in three settings this week: a conversation with a colleague about student assessments, a book I am reading about women writers, and a blog post I read on the exercise bike one morning.

The blog post is by Ben Orlin at Math With Bad Drawings from a few months ago, about an occasional topic of this blog: being less wrong each day [ for example, 1 and 2 ]. This sentence hit close enough to home that I saved it for later.

We struggle to tolerate censure, even the censure of idiots. Our social instrument is strung so tight, the least disturbance leaves us resonating for days.

Perhaps this struck a chord because I'm currently reading A Room of One's Own, by Virginia Woolf. In one early chapter, Woolf considers the many reasons that few women wrote poetry, fiction, or even non-fiction before the 19th century. One is that they had so little time and energy free to do so. Another is that they didn't have space to work alone, a room of one's own. But even women who had those things had to face a third obstacle: criticism from men and women alike that women couldn't, or shouldn't, write.

Why not shrug off the criticism and soldier on? Woolf discusses just how hard that is for anyone to do. Even many of our greatest writers, including Tennyson and Keats, obsessed over every unkind word said about them or their work. Woolf concludes:

Literature is strewn with the wreckage of men who have minded beyond reason the opinions of others.

Orlin's post, titled Err, and err, and err again; but less, and less, and less, makes an analogy between the advance of scientific knowledge and an infinite series in mathematics. Any finite sum in the series is "wrong", but if we add one more term, it is less wrong than the previous sum. Every new term takes us closer to the perfect answer.

a black and white portrait of a bearded man
Source: Wikipedia, public domain

He then goes on to wonder whether the same is, or could be, true of our moral development. His inspiration is American psychologist and philosopher William James. I have mentioned James as an inspiration myself a few times in this blog, most explicitly in Pragmatism and the Scientific Spirit, where I quote him as saying that consciousness is "not a thing or a place, but a process".

Orlin connects his passage on how humans receive criticism to James's personal practice of trying to listen only to the judgment of ever more noble critics, even if we have to imagine them into being:

"All progress in the social Self," James says, "is the substitution of higher tribunals for lower."

If we hold ourselves to a higher, more noble standard, we can grow. When we reach the next plateau, we look for the next higher standard to shoot for. This is an optimistic strategy for living life: we are always imperfect, but we aspire to grow in knowledge and moral development by becoming a little less wrong each step of the way. To do so, we try to focus our attention on the opinions of those whose standard draws us higher.

Reading James almost always leaves my spirit lighter. After Orlin's post, I feel a need to read The Principles of Psychology in full.

These two threads on how people respond to criticism came together when I chatted with a colleague this week about criticism from students. Each semester, we receive student assessments of our courses, which include multiple-choice ratings as well as written comments. The numbers can be a jolt, but their effect is nothing like that of the written comments. Invariably, at least one student writes a negative response, often an unkind or ungenerous one.

I told my colleague that this is recurring theme for almost every faculty member I have known: Twenty-nine students can say "this was a good course, and I really like the professor", but when one student writes something negative... that is the only comment we can think about.

The one bitter student in your assessments is probably not the ever more noble critic that James encourages you to focus on. But, yeah. Professors, like all people, are strung pretty tight when it comes to censure.

Fortunately, talking to others about the experience seems to help. And it may also remind us to be aware of how students respond to the things we say and do.

Anyway, I recommend both the Orlin blog post and Woolf's A Room of One's Own. The former is a quick read. The latter is a bit longer but a smooth read. Woolf writes well, and once my mind got on the book's wavelength, I found myself engaged deeply in her argument.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

January 06, 2024 10:41 AM


a man in a suit, behind a microphone and a bottle of water
Source: Wikipedia, unrestricted

My social media feed this week has included many notes and tributes on the passing of Niklaus Wirth, including his obituary from ETH Zurich, where he was a professor. Wirth was, of course, a Turing Award winner for his foundational work designing a sequence of programming languages.

Wirth's death reminded me of END DO, my post on the passing of John Backus, and before that a post on the passing of Kenneth Iverson. I have many fond memories related to Wirth as well.


Pascal was, I think, the fifth programming language I learned. After that, my language-learning history starts to speed up and blur. (I do think APL and Lisp came soon after.)

I learned BASIC first, as a junior in high school. This ultimately changed the trajectory of my life, as it planted the seeds for me to abandon a lifelong dream to be an architect.

Then at university, I learned Fortran in CS 1, PL/I in Data Structures (you want pointers!), and IBM 360/370 assembly language in a two-quarter sequence that also included JCL. Each of these language expanded my mind a little.

Pascal was the first language I learned "on my own". The fall of my junior year, I took my first course in algorithms. On Day 1, the professor announced that the department had decided to switch to Pascal in the intro course, so that's what we would use in this course.

"Um, prof, that's what the new CS majors are learning. We know Fortran and PL/I." He smiled, shrugged, and turned to the chalkboard. Class began.

After class, several of us headed immediately to the university library, checked out one Pascal book each, and headed back to the dorms to read. Later that week, we were all using Pascal to implement whatever classical algorithm we learned first in that course. Everything was fine.

I've always treasured that experience, even if it was little scary for a week or so. And don't worry: That professor turned out to be a good guy with whom I took several courses. He was a fellow chess player and ended up being the advisor on my senior project: a program to perform the Swiss system commonly used to run chess tournaments. I wrote that program in... Pascal. Up to that point, it was the largest and most complex program I had ever written solo. I still have the code.

The first course I taught as a tenure-track prof was my university's version of CS 1 -- using Pascal.

Fond memories all. I miss the language.

Wirth sightings in this blog

I did a quick search and found that Wirth has made an occasional appearance in this blog over the years.

• January 2006: Just a Course in Compilers

This was written at the beginning of my second offering of our compiler course, which I have taught and written about many times since. I had considered using as our textbook Wirth's Compiler Construction, a thin volume that builds a compiler for a subset of Wirth's Oberon programming language over the course of sixteen short chapters. It's a "just the facts and code" approach that appeals to me most days.

I didn't adopt the book for several reasons, not least of which that at the time Amazon showed only four copies available, starting at $274.70 each. With two decades of experience teaching the course now, I don't think I could ever really use this book with my undergrads, but it was a fun exercise for me to work through. It helped me think about compilers and my course.

Note: A PDF of Compiler Construction has been posted on the web for many years, but every time I link to it, the link ultimately disappears. I decided to mirror the files locally, so that the link will last as long as this post lasts:
[ Chapters 1-8 | Chapters 9-16 ]

• September 2007: Hype, or Disseminating Results?

... in which I quote Wirth's thoughts on why Pascal spread widely in the world but Modula and Oberon didn't. The passage comes from a short historical paper he wrote called "Pascal and its Successors". It's worth a read.

• April 2012: Intermediate Representations and Life Beyond the Compiler

This post mentions how Wirth's P-code IR ultimately lived on in the MIPS compiler suite long after the compiler which first implemented P-code.

• July 2016: Oberon: GoogleMaps as Desktop UI

... which notes that the Oberon spec defines the language's desktop as "an infinitely large two-dimensional space on which windows ... can be arranged".

• November 2017: Thousand-Year Software

This is my last post mentioning Wirth before today's. It refers to the same 1999 SIGPLAN Notices article that tells the P-code story discussed in my April 2012 post.

I repeat myself. Some stories remain evergreen in my mind.

The Title of This Post

I titled my post on the passing of John Backus END DO in homage to his intimate connection to Fortran. I wanted to do something similar for Wirth.

Pascal has a distinguished sequence to end a program: "end.". It seems a fitting way to remember the life of the person who created it and who gave the world so many programming experiences.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

December 31, 2023 1:35 PM

"I Want to Find Something to Learn That Excites Me"

In his year-end wrap-up, Greg Wilson writes:

I want to find something to learn that excites me. A new musical instrument is out because of my hand; I've thought about reviving my French, picking up some Spanish, diving into Postgres or machine learningn (yeah, yeah, I know, don't hate me), but none of them are making my heart race.

What he said. I want to find something to learn that excites me.

I just spent six months immersed in learning more about HTML, CSS, and JavaScript so that I could work with novice web developers. Picking up that project was one part personal choice and one part professional necessity. It worked out well. I really enjoyed studying the web development world and learned some powerful new tools. I will continue to use them as time and energy permit.

But I can't say that I am excited enough by the topic to keep going in this area. Right now, I am still burned out from the semester on a learning treadmill. I have a followup post to my early reactions about the course's JavaScript unit in the hopper, waiting for a little desire to finish it.

What now? There are parallels between my state and Wilson's.

  • After my first-ever trip to Europe in 2019, for a Dagstuhl seminar (brief mention here), my wife and I talked about a return trip, with a focus this time on Italy. Learning Italian was part of the nascent plan. Then came COVID, along with a loss of energy for travel. I still have learning Italian in my mind.
  • In the fall of 2020, the first full semester of the pandemic, I taught a database course for the first time (bookend posts here and here). I still have a few SQL projects and learning goals hanging around from that time, but none are calling me right now.
  • LLMs are the main focus of so many people's attention these days, but they still haven't lit up me up. In some ways, I envy David Humphrey, who fell in love with AI this year. Maybe something about LLMs will light me up one of these days. (As always, you should read David's stuff. He does neat work and shares it with the world.)

Unlike Wilson, I do not play a musical instrument. I did, however, learn a little basic piano twenty-five years ago when I was a Suzuki piano parent with my daughters. We still have our piano, and I harbor dreams of picking it back up and going farther some day. Right now doesn't seem to be that day.

I have several other possibilities on the back burner, particularly in the area of data analytics. I've been intrigued by the work on data-centric computing in education being done by Kathi Fisler and Shriram Krishnamurthi have been at Brown. I also will be reading a couple of their papers on program design and plan composition in the coming weeks as I prepare for my programming languages course this spring. Fisler and Krishnamurthi are coming at these topics from the side of CS education, but the topics are also related to my grad-school work in AI. Maybe these papers will ignite a spark.

Winter break is coming to an end soon. Like others, I'm thinking about 2024. Let's see what the coming weeks bring.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

November 24, 2023 12:17 PM

And Then Came JavaScript

It's been a long time again between posts. That seems to be the new normal. On top of that, though, teaching web development this fall for the first time has been soaking up all of my free hours in the evenings and over the weekends, which has left me little time to be sad about not blogging. I've certainly been writing plenty of text and a bit of code.

The course started off with a lot of positive energy. The students were excited to learn HTML and CSS. I made a few mistakes in how I organized and presented topics, but things went pretty well. By all accounts, students seemed to enjoy what they were learning and doing.

And then came JavaScript.

Well, along came real computer programming. It could have been Python or some other language, I think, but the transition to writing programs, even short bits of code, took the wind out of the students' excitement.

I was prepared for the possibility that the mood of the course would change when we shifted from CSS to JavaScript. A previous offering of the course had encountered a similar obstacle. Learning to program is a challenge. I'm still not convinced that learning to program is that much harder than a lot of things people learn to do, but it does take time.

As I prepared for the course last summer, I saw so many different approaches to teaching JavaScript for web development. Many assumed a lot of HTML/CSS/DOM background, certainly more than my students had picked up in six weeks. Others assumed programming experience most of my students didn't have, even when the approach said 'no experience necessary!'. So I had to find a middle path.

a colorful cube with sides labeled HTML, CSS, and JS
Source: MDN, CC BY-SA 2.5

My main source of inspiration in the first half of the course was David Humphrey's WEB 222 course, which was explicitly aimed at an audience of CS students with programming experience. So I knew that I had to do something different with my students, even as I used his wonderful course materials whenever I could.

My department had offered this course once many years ago, aimed at much the same kind of audience as mine, and the instructor — a good friend — shared all of his materials. I used that offering as a primary source of ideas for getting started with JavaScript, and I occasionally adapted examples for use in my class.

The results were not ideal. Students don't seem to have enjoyed this part of the course much at all. Some acknowledged that to me directly. Even the most engaged students seemed to lose a bit of their energy for the course. Performance also sagged. Based on homework solutions and a short exam, I would say that only one student has achieved the outcomes I had originally outlined for this unit.

I either expected too much or did not do a good enough job helping students get to where I wanted them to be.

I have to do better next time.

But how?

Programming isn't as hard as some people tell us, but most of us can't learn to do it in five or six weeks, at least not enough to become very productive. We don't expect students to master all of CSS or even HTML in such a short time, so we can't expect them to master JavaScript either. The difference is that there seems to be a smooth on-ramp for learning HTML and CSS on the way to mastery, while JavaScript (or any other programming language) presents a steep climb, with occasional plateaus.

For now, I am thinking that the key to doing better is to focus on an even narrower set of concepts and skills.

If people starting from scratch can't learn all of JavaScript in five or six weeks, or even enough to be super-productive, what useful skills can they learn in that time? For this course I trimmed down the set of topics that we might cover in an intro CS considerably, but I think I need to trim even more and — more importantly — choose topics and examples that are even more embedded in the act of web development.

Earlier this week, a sudden burst of thought outlined something like this:

  • document.querySelector() to select an element in a page
  • simple assignment statements to modify innerText, innerHTML, and various style attributes
  • parameterizing changes to an element to create a function
  • document.querySelectorAll() to select collections of elements in a page
  • forEach to process every element in a collection
  • guarded actions to select items in the collection using if statements, without else clauses

That is a lot to learn in five weeks! Even so, it cuts way back on several topics I tried cover this time, such as a more general discussion of objects, arrays, and boolean values, and a deeper look at the DOM. And it eliminates even mentioning several topics altogether:

  • if-else statements
  • while statements
  • counted for loops and, more generally, map-like behavior
  • any fiddling with numbers and arithmetic, which are often used to learn assignment statements, if statements, and function

There are so many things a programmer can't do without these concepts, such as writing an indefinite data validation loop or really understanding what's going on in the DOM tree. But trying to cover all of those topics too did not result in students being able to do them either! I think it left them confused, with so many new ideas jumbled in their minds, and a general dissatisfaction at being unable to use JavaScript effectively.

Of course I would want to build hooks into the course for students who want to go deeper and are ready to do so. There is so much good material on the web for people who are ready for more. Providing more enriched opportunities for advanced students is easier than designing learning opportunities for beginners.

Can something like this work?

I won't know for a while. It will be at least a year before I teach this course again. I wish I could teach it again sooner, so that I could try some of my new ideas and get feedback on them sooner. Such is the curse of a university calendar and once-yearly offerings.

It's too late to make any big changes in trajectory this semester. We have only two weeks after the current one-week Thanksgiving break. Next week, we will focus on input forms (HTML), styling (CSS), and a little data validation (HTML+JavaScript). I hope that this return to HTML+CSS helps us end the course on a positive note. I'd like for students to finish with a good feeling about all they have learned and now can do.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

October 31, 2023 7:12 PM

The Spirit of Spelunking

Last month, Gus Mueller announced v7.4.3 of his image-editing tool Acorn. This release has a fun little extra built in:

One more super geeky thing I've added is a JavaScript Console:


This tool is really meant for folks developing plugins in Acorn, and it is only accessible from the Command Bar, but a part of me absolutely loves pointing out little things like this. I was just chatting with Brent Simmons the other day at Xcoders how you can't really spelunk in apps any more because of all the restrictions that are (justifiably) put on recent MacOS releases. While a console isn't exactly a spelunking tool, I still think it's kind of cool and fun and maybe someone will discover it accidentally and that will inspire them to do stupid and entertaining things like we used to do back in the 10.x days.

I have had JavaScript consoles on my mind a lot in the last few weeks. My students and I have used the developer tools in our browsers as part of my web development course for non-majors. To be honest, I had never used a JavaScript console until this summer, when I began preparing for the course in earnest. REPLs are, of course, a big part of the programming background, from Lisp to Racket to Ruby to Python, so I took to the console with ease and joy. (My past experience with JavaScript was mostly in Node.js, which has its own REPL.) We just started our fourth week studying JavaScript in class, so my students have started getting used to the console. At the outset, it was new to most of them, who have never programmed before. Our attention has now turned to interacting with the DOM and manipulating the content of web page. It's been a lot of fun for me. I'm not sure how it feels for all of my students, though. Many came to the course for web design and really enjoy HTML and CSS. JavaScript, on the other hand, is... programming: more syntax, more semantics, and a lot of new details just to select, say, the third h3 on the page.

Sometimes, you just gotta work over the initial hump to sense the power and fun. Some of them are getting there.

Today I had great fun showing them how to add some simple search functionality to a web page. It was our first big exercise using document.querySelectorAll() and processing a collection of HTML elements. Soon we'll learn about text fields and buttons and events, at which point my The Books of Bokonon will become much more useful to the many readers who still find pleasure in it. Just last night that page got its first modern web styling in the form of a CSS style sheet. For its first twenty-four years of existence, it was all 1990s-era HTML and pseudo-layout using <center>, <hr>, and <br> tags.

Anyway, I appreciate Gus's excitement at adding a console to Acorn, making his tool a place to play as well as work. Spread the joy.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

September 22, 2023 8:38 PM

Time and Words

Earlier this week, I posted an item on Mastodon:

After a few months studying and using CSS, every once in a while I am able to change a style sheet and cause something I want to happen. It feels wonderful. Pretty soon, though, I'll make a typo somewhere, or misunderstand a property, and not be able to make anything useful happen. That makes me feel like I'm drowning in complexity.

Thankfully, the occasional wonderful feelings — and my strange willingness to struggle with programming errors — pull me forward.

I've been learning a lot while preparing to teach to our web development course [ 1 | 2 ]. Occasionally, I feel incompetent, or not very bright. It's good for me.

I haven't been blogging lately, but I've been writing lots of words. I've also been re-purposing and adapting many other words that are licensed to be reusable (thanks, David Humphrey and John Davis). Prepping a new course is usually prime blogging time for me, with my mind in a constant state of churn, but this course has me drowning in work to do. There is so much to learn, and so much new material — readings, session plans and notes, examples, homework assignments — to create.

I have made a few notes along the way, hoping to expand them into posts. Today they become part of this post.

VS Code

This is my first time in a long time using an editor configured to auto-complete and do all the modern things that developers expect these days. I figured, new tool, why not try a new workflow...

After a short period of breaking in, I'm quite enjoying the experience. One feature I didn't expect to use so much is the ability to collapse an HTML element. In a large HTML file, this has been a game changer for me. Yes, I know, this is old news to most of you. But as my brother loves to say when he gets something used or watches a movie everyone else has already seen, "But, hey, it's new to me!" VS Code's auto-complete across HTML, CSS, and JavaScript, with built-in documentation and links to MDN's more complete documentation, lets me type code much faster than ever before. It made me think of one of my favorite Kent Beck lines:

As the speed of development approaches infinity, reuse becomes irrelevant.

When programming, I often copy, paste, and adapt previous code. In VS Code, I have found myself moving fast enough that copy, paste, and adapt would slow me down. That sort of reuse has become irrelevant.

Examples > Prose

The class sessions for which I have written the longest and most complete notes for my students (and me) tend to be the ones for which I have the fewest, or least well-developed, code examples. The reverse is also true: lots of good examples and code tends to mean smaller class notes. Sometimes that is because I run out of time to write much prose to accompany the session. Just as often, though, it's because the examples give us plenty to do live in class, where the learning happens in the flow of writing and examining code.

This confirms something I've observed over many years of teaching: Examples First tends to work better for most students, even people like me who fancy themselves as top-down thinkers. Good examples and code exercises can create the conditions in which abstract knowledge can be learned. This is a sturdy pedagogical pattern.

Concepts and Patterns

There is so, so much to CSS! HTML itself has a lot of details for new coders to master before they reach fluency. Many of the websites aimed at teaching and presenting these topics quickly begin to feel like a downpour of information, even when the authors try to organize it all. It's too easy to fall into, "And then there's this other property...".

After a few weeks, I've settled into trying to help students learn two kinds of things for each topic:

  • a couple of basic concepts or principles
  • a few helpful patterns
My challenge is that I am still new enough to modern web design that identifying either in advance is a challenge. My understanding is constantly evolving, so my examples and notes are evolving, too. I will be better next time, or so I hope.


We are only five weeks into a fifteen week semester, so take any conclusions I draw with a grain of salt. We also haven't gotten to JavaScript yet, the teaching and learning of which will present a different sort of challenge than HTML and CSS with students who have little or no experience programming. Maybe I will make time to write up our experiences with JavaScript in a few weeks.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

July 31, 2023 2:35 PM

Learning CSS By Doing It

I ran across this blog post earlier this summer when browsing articles on CSS, as one does while learning CSS for a fall course. Near the end, the writer says:

This is thoroughly exciting to me, and I don't wanna whine about improvements in CSS, but it's a bit concerning since I feel like what the web is now capable of is slipping through my fingers. And I guess that's what I'm worried about; I no longer have a good idea of how these things interact with each other, or where the frontier is now.

The map of CSS in my mind is real messy, confused, and teetering with details that I can't keep straight in my head.

Imagine how someone feels as they learn CSS basically from the beginning and tries to get a handle both on how to use it effectively and how to teach it effectively. There is so much there... The good news, of course, is that our course is for folks with no experience, learning the basics of HTML, CSS, and JavaScript from the beginning, so there is only so far we can hope to go in fifteen weeks anyway.

My impressions of HTML and CSS at this point are quite similar: very little syntax, at least for big chunks of the use cases, and lots and lots of vocabulary. Having convenient access to documentation such as that available at developer.mozilla.org via the web and inside VS Code makes exploring all of the options more manageable in context.

I've been watching Dave Humphrey's videos for his WEB 222 course at Seneca College and learning tons. Special thanks to Dave for showing me a neat technique to use when learning -- and teaching -- web development: take a page you use all the time and try to recreate it using HTML and CSS, without looking at the page's own styles. He has done that a couple times now in his videos, and I was able to integrate the ideas we covered about the two languages in previous videos as Dave made the magic work. I have tried it once on my own. It's good fun and a challenging exercise.

Learning layout by viewing page source used to be easier in the old days, when pages were simpler and didn't include dozens of CSS imports or thousands of scripts. Accepting the extra challenge of not looking at a page's styles in 2023 is usually the simpler path.

Two re-creations I have on tap for myself in the coming days are a simple Wikipedia-like page for myself (I'm not notable enough to have an actual Wikipedia page, of course) and a page that acts like my Mastodon home page, with anchored sidebars and a scrolling feed in between. Wish me luck.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

July 10, 2023 12:28 PM

What We Know Affects What We See

Last time I posted this passage from Shop Class as Soulcraft, by Matthew Crawford:

Countless times since that day, a more experienced mechanic has pointed out to me something that was right in front of my face, but which I lacked the knowledge to see. It is an uncanny experience; the raw sensual data reaching my eye before and after are the same, but without the pertinent framework of meaning, the features in question are invisible. Once they have been pointed out, it seems impossible that I should not have seen them before.

We perceive in part based on what we know. A lack of knowledge can prevent us from seeing what is right in front of us. Our brains and eyes work together, and without a perceptual frame, they don't make sense of the pattern. Once we learn something, our eyes -- and brains -- can.

This reminds me of a line from the movie The Santa Clause, which my family watched several times when my daughters were younger. The new Santa Claus is at the North Pole, watching magical things outside his window, and comments to the elf whose been helping him, "I see it, but I don't believe it." She replies that adults don't understand: "Seeing isn't believing; believing is seeing." As a mechanic, Crawford came to understand that knowing is seeing.

Later in the book, Crawford describes another way that knowing and perceiving interact with one another, this time with negative results. He had been struggling to figure out why there was no spark at the spark plugs in his VW Bug, and his father -- an academic, not a mechanic -- told him about Ohm's Law:

Ohm's law is something explicit and rulelike, and is true in the way that propositions are true. Its utter simplicity makes it beautiful; a mind in possession of this equation is charmed with a sense of its own competence. We feel we have access to something universal, and this affords a pleasure that is quasi-religious, perhaps. But this charm of competence can get in the way of noticing things; it can displace, or perhaps hamper the development of, a different kind of knowledge that may be difficult to bring to explicit awareness, but is superior as a practical matter. It superiority lies in the fact that it begins with the typical rather than the universal, so it goes more rapidly and directly to particular causes, the kind that actually tend to cause ignition problems.

Rule-based, universal knowledge imposes a frame on the scene. Unfortunately, its universal nature can impede perception by blinding us to the particular details of the situation we are actually in. Instead of seeing what is there, we see the scene as our knowledge would have it.

the cover of the book Drawing on the Right Side of the Brain

This reminds me of a story and a technique from the book Drawing on the Right Side of the Brain, which I first wrote about in the earliest days of this blog. When asked to draw a chair, most people barely even look at the chair in front of them. Instead, they start drawing their idea of a chair, supplemented by a few details of the actual chair they see. That works about as well as diagnosing an engine by diagnosing your mind's eye of an engine, rather than the mess of parts in front of you.

In that blog post, I reported my experience with one of Edwards's techniques for seeing the chair, drawing the negative space:

One of her exercises asked the student to draw a chair. But, rather than trying to draw the chair itself, the student is to draw the space around the chair. You know, that little area hemmed in between the legs of the chair and the floor; the space between the bottom of the chair's back and its seat; and the space that is the rest of the room around the chair. In focusing on these spaces, I had to actually look at the space, because I don't have an image in my brain of an idealized space between the bottom of the chair's back and its seat. I had to look at the angles, and the shading, and that flaw in the seat fabric that makes the space seem a little ragged.

Sometimes, we have to trick our eyes into seeing, because otherwise our brains tell us what we see before we actually look at the scene. Abstract universal knowledge helps us reason about what we see, but it can also impede us from seeing in the first place.

What we know both enables and hampers what we perceive. This idea has me thinking about how my students this fall, non-CS majors who want to learn how to develop web sites, will encounter the course. Most will be novice programmers who don't know what they see when they are looking at code, or perhaps even at a page rendered in the browser. Debugging code will be a big part of their experience this semester. Are there exercises I can give them to help them see accurately?

As I said in my previous post, there's lots of good stuff happening in my brain as I read this book. Perhaps more posts will follow.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

July 04, 2023 11:55 AM

Time Out

Any man can call time out, but no man
can say how long the time out will be.
-- Books of Bokonon

I realized early last week that it had been a while since I blogged. June was a morass of administrative work, mostly summer orientation. Over the month, I had made notes for several potential posts, on my web dev course, on the latest book I was reading, but never found -- made -- time to write a full post. I figured this would be a light month, only a couple of short posts, if I only I could squeeze another one in by Friday.

Then I saw that the date of my most recent post was May 26, with the request for ideas about the web course coming a week before.

I no longer trust my sense of time.

This blog has certainly become much quieter over the years, due in part to the kind and amount of work I do and in part to choices I make outside of work. I may even have gone a month between posts a few fallow times in the past. But June 2023 became my first calendar month with zero posts.

It's somewhat surprising that a summer month would be the first to shut me out. Summer is a time of no classes to teach, fewer student and faculty issues to deal with, and fewer distinct job duties. This occurrence is a testament to how much orientation occupies many of my summer days, and how at other times I just want to be AFK.

A real post or two are on their way, I promise -- a promise to myself, as well as to any of you who are missing my posts in your newsreader. In the meantime...

On the web dev course: thanks to everyone who sent thoughts! There were a few unanimous, or near unanimous, suggestions, such as to have students use VS code. I am now learning it myself, and getting used to an IDE that autocompletes pairs such as "". My main prep activity up to this point has been watching David Humphrey's videos for WEB 222. I have been learning a little HTML and JavaScript and a lot of CSS and how these tools work together on the modern web. I'm also learning how to teach these topics, while thinking about the differences between my student audience and David's.

On the latest book: I'm currently reading Shop Class as Soulcraft, by Matthew Crawford. It came out in 2010 and, though several people recommended it to me then, I had never gotten around to it. This book is prompting so many ideas and thoughts that I'm constantly jotting down notes and thinking about how these ideas might affect my teaching and my practice as a programmer. I have a few short posts in mind based on the book, if only I commit time to flesh them out. Here are two passages, one short and one long, from my notes.

Fixing things may be a cure for narcissism.

Countless times since that day, a more experienced mechanic has pointed out to me something that was right in front of my face, but which I lacked the knowledge to see. It is an uncanny experience; the raw sensual data reaching my eye before and after are the same, but without the pertinent framework of meaning, the features in question are invisible. Once they have been pointed out, it seems impossible that I should not have seen them before.

Both strike a chord for me as I learn an area I know only the surface of. Learning changes us.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

May 19, 2023 2:57 PM

Help! Teaching Web Development in 2023

With the exception of teaching our database course during the COVID year, I have been teaching a stable pair of courses for the last many semesters: Programming Languages in the spring and our compilers course, Translation of Programming Languages, in the fall. That will change this fall due to some issues with enrollments and course demands. I'll be teaching a course in client-side web development.

The official number and title of the course are "CS 1100 Web Development: Client-Side Coding". The catalog description for the course was written years ago by committee:

Client-side web development adhering to current Web standards. Includes by-hand web page development involving basic HTML, CSS, data acquisition using forms, and JavaScript for data validation and simple web-based tools.

As you might guess from the 1000-level number, this is an introductory course suitable for even first-year students. Learning to use HTML, CSS, and Javascript effectively is the focal point. It was designed as a service course for non-majors, with the primary audience these days being students in our Interactive Digital Studies program. Students in that program learn some HTML and CSS in another course, but that course is not a prerequisite to ours. A few students will come in with a little HTML5+CSS3 experience, but not all.

So that's where I am. As I mentioned, this is one of my first courses to design from scratch in a long time. Other than Database Systems, we have to go back to Software Engineering in 2009. Starting from scratch is fun but can be daunting, especially in a course outside my core competency of hard-core computer science.

The really big change, though, was mentioned two paragraphs ago: non-majors. I don't think I've taught non-majors since teaching my university's capstone 21 years ago -- so long ago that this blog did not yet exist. I haven't taught a non-majors' programming course in even longer, 25 years or more, when I last taught BASIC. That is so long ago that their was no "Visual" in the language name!

So: new area, new content, new target audience. I have a lot of work to do this summer.

I could use some advice from those of you who do web development for a living, who know someone who does, or who are more up to date on the field than I.

Generally, what should a course with this title and catalog description be teaching to beginners in 2023?

Specifically, can you point me toward...

  • similar courses with material online that I could learn from?
  • resources for students to use as they learn: websites, videos, even books?

For example, a former student and now friend mentioned that the w3schools website includes a JavaScript tutorial which allows students to type and test code within the web browser. That might simplify practice greatly for non-CS students while they are learning other development tools.

I have so many questions to answer about tools in particular right now: Should we use an IDE or a simple text editor? Which one? Should we learn raw JavaScript or a simple framework? If a framework, which one?

This isn't a job-training course, but to the extent that's reasonable I would like for students to see a reasonable facsimile of what they might encounter out in industry.

Thinking back, I guess I'm glad now that I decided to play some around with JavaScript in 2022... At least I now have more context for evaluatins the options available for this course.

If you have any thoughts or suggestions, please do send them along. Sending email or replying on Mastodon or Twitter all work. I'll keep you posted on what I learn.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

May 07, 2023 8:36 AM

"The Society for the Diffusion of Useful Knowledge"

I just started reading Joshua Kendall's The Man Who Made Lists, a story about Peter Mark Roget. Long before compiling his namesake thesaurus, Roget was a medical doctor with a local practice. After a family tragedy, though, he returned to teaching and became a science writer:

In the 1820s and 1830s, Roget would publish three hundred thousand words in the Encyclopaedia Brittanica and also several lengthy review articles for the Society for the Diffusion of Useful Knowledge, the organization affiliated with the new University of London, which sought to enable the British working class to educate itself.

What a noble goal, enabling the working class to educate itself. And what a cool name: The Society for the Diffusion of Useful Knowledge!

For many years, my university has provided a series of talks for retirees, on topics from various departments on campus. This is a fine public service, though without the grand vision -- or the wonderful name -- of the Society for the Diffusion of Useful Knowledge. I suspect that most universities depend too much on tuition and lower costs these days to mount an ambitious effort to enable the working class to educate itself.

Mental illness ran in Roget's family. Kendall wonders if Roget's "lifelong desire to bring order to the world" -- through his lecturing, his writing, and ultimately his thesaurus, which attempted to classify every word and concept -- may have "insulated him from his turbulent emotions" and helped him stave off the depression that afflicted several of his family members.

Academics often live an obsessive connection with the disciplines they practice and study. Certainly that sort of focus can can be bad for a person when taken too far. (Is it possible for an obsession not to go too far?) For me, though, the focus of studying something deeply, organizing its parts, and trying to communicate it to others through my courses and writing has always felt like a gift. The activity has healing properties all its own.

In any case, the name "The Society for the Diffusion of Useful Knowledge" made me smile. Reading has the power to heal, too.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

April 23, 2023 12:09 PM

PyCon Day 2

Another way that attending a virtual conference is like the in-person experience: you can oversleep, or lose track of time. After a long morning of activity before the time-shifted start of Day 2, I took a nap before the 11:45 talk, and...

Talk 1: Python's Syntactic Sugar

Grrr. I missed the first two-thirds of this talk, which I greatly anticipated, but I slept longer than I planned. My body must have needed more than I was giving it.

I saw enough of the talk, though, to know I want to watch the video on YouTube when it shows up. This topic is one of my favorite topics in programming languages: What is the smallest set of features we need to implement the rest of the language? The speaker spent a couple of years implementing various Python features in terms of others, and arrived at a list of only ten that he could not translate away. The rest are sugar. I missed the list at the beginning of the talk, but I gathered a few of its members in the ten minutes I watched: while, raise, and try/except.

I love this kind of exercise: "How can you translate the statement if X: Y into one that uses only core features?" Here's one attempt the speaker gave:

        while X:
	    raise _DONE
    except _DONE:

I was today days old when I learned that Python's bool subclasses int, that True == 1, and that False == 0. That bit of knowledge was worth interrupting my nap to catch the end of the talk. Even better, this talk was based on a series of blog posts. Video is okay, but I love to read and play with ideas in written form. This series vaults to the top of my reading list for the coming days.

Talk 2: Subclassing, Composition, Python, and You

Okay, so this guy doesn't like subclasses much. Fair enough, but... some of his concerns seem to be more about the way Python classes work (open borders with their super- and subclasses) than with the idea itself. He showed a lot of ways one can go wrong with arcane uses of Python subclassing, things I've never thought to do with a subclass in my many years doing OO programming. There are plenty of simpler uses of inheritance that are useful and understandable.

Still, I liked this talk, and the speaker. He was honest about his biases, and he clearly cares about programs and programmers. His excitement gave the talk energy. The second half of the talk included a few good design examples, using subclassing and composition together to achieve various ends. It also recommended the book Architecture Patterns with Python. I haven't read a new software patterns book in a while, so I'll give this one a look.

Toward the end, the speaker referenced the line "Software engineering is programming integrated over time." Apparently, this is a Google thing, but it was new to me. Clever. I'll think on it.

Talk 3: How We Are Making CPython Faster -- Past, Present and Future

I did not realize that, until Python 3.11, efforts to make the interpreter had been rather limited. The speaker mentioned one improvement made in 3.7 to optimize the typical method invocation, obj.meth(arg), and one in 3.8 that sped up global variable access by using a cache. There are others, but nothing systematic.

At this point, the talk became mutually recursive with the Friday talk "Inside CPython 3.11's New Specializing, Adaptive Interpreter". The speaker asked us to go watch that talk and return. If I were more ambitious, I'd add a link to that talk now, but I'll let you any of you are interested to visit yesterday's post and scroll down two paragraphs.

He then continued with improvements currently in the works, including:

  • efforts to optimize over larger regions, such as the different elements of a function call
  • use of partial evaluation when possible
  • specialization of code
  • efforts to speed up memory management and garbage collection

He also mentions possible improvements related to C extension code, but I didn't catch the substance of this one. The speaker offered the audience a pithy takeaway from his talk: Python is always getting faster. Do the planet a favor and upgrade to the latest version as soon as you can. That's a nice hook.

There was lots of good stuff here. Whenever I hear compiler talks like this, I almost immediately start thinking about how I might work some of the ideas into my compiler course. To do more with optimization, we would have to move faster through construction of a baseline compiler, skipping some or all of the classic material. That's a trade-off I've been reluctant to make, given the course's role in our curriculum as a compilers-for-everyone experience. I remain tempted, though, and open to a different treatment.

Talk 4: The Lost Art of Diagrams: Making Complex Ideas Easy to See with Python

Early on, this talk contained a line that programmers sometimes need to remember: Good documentation shows respect for users. Good diagrams, said the speaker, can improve users' lives. The talk was a nice general introduction to some of the design choices available to us as we create diagrams, including the use of color, shading, and shapes (Venn diagrams, concentric circles, etc.). It then discussed a few tools one can use to generate better diagrams. The one that appealed most to me was Mermaid.js, which uses a Markdown-like syntax that reminded me of GraphViz's Dot language. My students and use GraphViz, so picking up Mermaid might be a comfortable task.


My second day at virtual PyCon confirmed that attending was a good choice. I've seen enough language-specific material to get me thinking new thoughts about my courses, plus a few other topics to broaden the experience. A nice break from the semester's grind.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

April 09, 2023 8:24 AM

It Was Just Revision

There are several revised approaches to "what's the deal with the ring?" presented in "The History of The Lord of the Rings", and, as you read through the drafts, the material just ... slowly gets better! Bit by bit, the familiar angles emerge. There seems not to have been any magic moment: no electric thought in the bathtub, circa 1931, that sent Tolkien rushing to find a pen.

It was just revision.


... if Tolkien can find his way to the One Ring in the middle of the fifth draft, so can I, and so can you.

-- Robin Sloan, How The Ring Got Good

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

March 29, 2023 2:39 PM

Fighting Entropy in Class

On Friday, I wrote a note to myself about updating an upcoming class session:

Clean out the old cruft. Simplify, simplify, simplify! I want students to grok the idea and the implementation. All that Lisp and Scheme history is fun for me, but it gets in the students' way.

This is part of an ongoing battle for me. Intellectually, I know to design class sessions and activities focused on where students are and what they need to do in order to learn. Yet it continually happens that I strike upon a good approach for a session, and then over the years I stick a little extra in here and there; within a few iterations I have a big ball of mud. Or I fool myself that some bit of history that I find fascinating is somehow essential for students to learn about, too, so I keep it in a session. Over the years, the history grows more and more distant; the needs of the session evolve, but I keep the old trivia in there, filling up time and distracting my students.

It's hard.

The specific case in question here is a session in my programming languages course called Creating New Syntax. The session has the modest goal of introducing students to the idea of using macros and other tools to define new syntactic constructs in a language. My students come into the course with no Racket or Lisp experience, and only a few have enough experience with C/C++ that they may have seen its textual macros. My plan for this session is to expose them to a few ideas and then to demonstrate one of Racket's wonderful facilities for creating new syntax. Given the other demands of the course, we don't have time to go deep, only to get a taste.

[In my dreams, I sometimes imagine reorienting this part of my course around something like Matthew Butterick's Beautiful Racket... Maybe someday.]

Looking at my notes for this session on Friday, I remembered just how overloaded and distracting the session has become. Over the years, I've pared away the extraneous material on macros in Lisp and C, but now it has evolved to include too many ideas and incomplete examples of macros in Racket. Each by itself might make for a useful part of the story. Together, they pull attention here and there without ever closing the deal.

I feel like the story I've been telling is getting in the way of the one or two key ideas about this topic I want students to walk away from the course with. It's time to clean the session up -- to make some major changes -- and tell a more effective story.

The specific idea I seized upon on Friday is an old idea I've had in mind for a while but never tried: adding a Python-like for-loop:

    (for i in lst: (sqrt i))

[Yes, I know that Racket already has a fine set of for-loops! This is just a simple form that lets my students connect their fondness for Python with the topic at hand.]

This functional loop is equivalent to a Racket map expression:

    (map (lambda (i)
           (sqrt i))

We can write a simple list-to-list translator that converts the loop to an equivalent map:

    (define for-to-map
      (lambda (for-exp)
        (let ((var (second for-exp))
              (lst (fourth for-exp))
              (exp (sixth for-exp)))
          (list 'map
                (list 'lambda (list var) exp)

This code handles only the surface syntax of the new form. To add it to the language, we'd have to recursively translate the form. But this simple function alone demonstrates the idea of translational semantics, and shows just how easy it can be to convert a simple syntactic abstraction into an equivalent core form.

Racket, of course, gives us better options! Here is the same transformer using the syntax-rules operator:

    (define-syntax for-p
      (syntax-rules (in :)
        ( (for-p var in lst : exp)
            (map (lambda (var) exp) lst) )  ))

So easy. So powerful. So clear. And this does more than translate surface syntax in the form of a Racket list; it enables the Racket language processor to expand the expression in place and execute the result:

    > (for-p i in (range 0 10):
        (sqrt i))

This small example demonstrates the key idea about macros and syntax transformers that I want students to take from this session. I plan to open the session with for-p, and then move on to range-case, a more complex operator that demonstrates more of syntax-rules's range and power.

This sets me up for a fun session in a little over a week. I'm excited to see how it plays with students. Renewed simplicity and focus should help.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 12, 2023 9:00 AM

A Spectator to Phase Change

Robin Sloan speculates that language-learning models like ChatGPT have gone through a phase change in what they can accomplish.

AI at this moment feels like a mash-up of programming and biology. The programming part is obvious; the biology part becomes apparent when you see AI engineers probing their own creations the way scientists might probe a mouse in a lab.

Like so many people, I find my social media and blog feeds filled with ChatGPT and LLMs and DALL-E and ... speculation about what these tools mean for (1) the production of text and code, and (2) learning to write and program. A lot of that speculation is tinged with fear.

I admire Sloan's effort to be constructive in his approach to the uncertainty:

I've found it helpful, these past few years, to frame my anxieties and dissatisfactions as questions. For example, fed up with the state of social media, I asked: what do I want from the internet, anyway?

It turns out I had an answer to that question.

Where the GPT-alikes are concerned, a question that's emerging for me is:

What could I do with a universal function — a tool for turning just about any X into just about any Y with plain language instructions?

I admit that I am reacting to these developments slowly compared to many people. That's my style in most things: I am more likely to under-react to a change than to over-react, especially at the onset of the change. In this case, there is no chance of immediate peril, so waiting to see what happens as people use these tools seems like a reasonable reasonable. I haven't made any effort to use these tools actively (or even been moved to), so any speculating I do would be uninformed by personal experience.

Instead, I read as people whose work I respect experiment with these tools and try to make sense of them. Occasionally, I draw a small, tentative conclusion, such as that prompting these generators is a lot like prompting students. After a few months of reading and a little reflection, I still think the biggest risk we face is probably that we tend to change the world around us to accommodate our technologies. If we put these tools to work for us in ways that enhance what we do, then the accommodation will pay off. If not, then we may, as Daniel Steinberg wrote in one of his newsletters, stop asking the questions we want to ask and start asking only the questions these tools can answer.

Professionally, I think most about the effect that ChatGPT and its ilk will have on programming and CS education. In these regards, I've been paying special attention to reports from David Humphrey, such as this blog post on his university's attempt to grapple the widespread availability of these tools. David has approached OpenAI with an open mind and written thoughtfully about the promise and the risk. For example, he has written a lot of code with an LLM assistant and found it improving his ability both to write code and to think about problems. Advanced CS students can benefit from this kind of assistance, too, but David wonders how such tools might interfere with students first learning to program.

What do we educators want from generative programming tools anyway? What do I as a programmer and educator want from them?

So, at this point, my personal interaction with the phase change that Sloan describes has been mostly passive: I read about what others are doing and think about the results of their exploration. Perhaps this post is a guilty conscience asserting that I should be doing more. Really, though, I think of it more as an active form of inaction: an effort to collect some of my thinking as I slowly respond to the changes that are coming. Perhaps some day soon I will feel moved to use of these tools as I write code of my own. For now, though, I am content to watch from the sidelines. You can learn a lot just by watching.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Software Development, Teaching and Learning

March 05, 2023 9:47 AM

Context Matters

In this episode of Conversations With Tyler, Cowen asks economist Jeffrey Sachs if he agrees with several other economists' bearish views on a particular issue. Sachs says they "have been wrong ... for 20 years", laughs, and goes on to say:

They just got it wrong time and again. They had failed to understand, and the same with [another economist]. It's the same story. It doesn't fit our model exactly, so it can't happen. It's got to collapse. That's not right. It's happening. That's the story of our time. It's happening.

"It doesn't fit our model, so it can't happen." But it is happening.

When your model keeps saying that something can't happen, but it keeps happening anyway, you may want to reconsider your model. Otherwise, you may miss the dominant story of the era -- not to mention being continually wrong.

Sachs spends much of his time with Cowen emphasizing the importance of context in determining which model to use and which actions to take. This is essential in economics because the world it studies is simply too complex for the models we have now, even the complex models.

I think Sachs's insight applies to any discipline that works with people, including education and software development.

The topic of education even comes up toward the end of the conversation, when Cowen asks Sachs how to "fix graduate education in economics". Sachs says that one of its problems is that they teach econ as if there were "four underlying, natural forces of the social universe" rather than studying the specific context of particular problems.

He goes on to highlight an approach that is affecting every discipline now touched by data analytics:

We have so much statistical machinery to ask the question, "What can you learn from this dataset?" That's the wrong question because the dataset is always a tiny, tiny fraction of what you can know about the problem that you're studying.

Every interesting problem is bigger than any dataset we build from it. The details of the problem matter. Again: context. Sachs suggests that we shouldn't teach econ like physics, with Maxwell's overarching equations, but like biology, with the seemingly arbitrary details of DNA.

In my mind, I immediately began thinking about my discipline. We shouldn't teach software development (or econ!) like pure math. We should teach it as a mix of principles and context, generalities and specific details.

There's almost always a tension in CS programs between timeless knowledge and the details of specific languages, libraries, and tools. Most of students don't go on to become theoretical computer scientists; they go out to work in the world of messy details, details that keep evolving and morphing into something new.

That makes our job harder than teaching math or some sciences because, like economics:

... we're not studying a stable environment. We're studying a changing environment. Whatever we study in depth will be out of date. We're looking at a moving target.

That dynamic environment creates a challenge for those of us teaching software development or any computing as practiced in the world. CS professors have to constantly be moving, so as not to fall our of date. But they also have to try to identify the enduring principles that their students can count on as they go on to work in the world for several decades.

To be honest, that's part of the fun for many of us CS profs. But it's also why so many CS profs can burn out after 15 or 20 years. A never-ending marathon can wear anyone out.

Anyway, I found Cowens' conversation with Jeffrey Sachs to be surprisingly stimulating, both for thinking about economics and for thinking about software.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

February 18, 2023 11:16 AM

CS Students Should Take Their Other Courses Seriously, Too

(These days, I'm posting a bit more on Mastodon. It has a higher character limit than Twitter, so I sometimes write longer posts, including quoted passages. Those long posts start to blur in length and content with blog posts. In an effort to blog more, and to preserve writing that may have longer value than a social media post provides, I may start capturing threads there as blog posts here. This post originated as a Mastodon post last week.)


This post contains one of the reasons I tell prospective CS students to take their humanities and social science courses seriously:

In short, the key skill for making sense of the world of information is developing the ability to accurately and neutrally summarize some body of information in your own words.

The original poster responded that it wasn't until going back to pursue a master's degree in library and information science that this lesson hit home for him.

I always valued my humanities and social science courses, both because I enjoyed them and because they let me practice valuable skills that my CS and math courses didn't exercise. But this lesson hit home for me in a different way after I became a professor.

Over my years teaching, I've seen students succeed and struggle in a lot of different ways. The ability to read and synthesize information with facility is one of the main markers of success, one of the things that can differentiate between students who do well and those who don't. It's also hard to develop this skill after students get to college. Nearly every course and major depends on it, even technical courses, even courses and majors that don't foreground this kind of skill. Without it, students keep falling farther behind. It's hard to develop the skill quickly enough to not fall so far behind that success feels impossible.

So, kids and parents, when you ask how to prepare to succeed as a CS student while in high school, one of my answers will almost always be: take four years of courses in every core area, including English and social science. The skills you develop and practice there will pay off many-fold in college.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

February 11, 2023 1:53 PM

What does it take to succeed as a CS student?

Today I received an email message similar to this:

I didn't do very well in my first semester, so I'm looking for ways to do better this time around. Do you have any ideas about study resources or tips for succeeding in CS courses?

As an advisor, I'm occasionally asked by students for advice of this sort. As department head, I receive even more queries, because early on I am the faculty member students know best, from campus visits and orientation advising.

When such students have already attempted a CS course or two, my first step is always to learn more about their situation. That way, I can offer suggestions suited to their specific needs.

Sometimes, though, the request comes from a high school student, or a high school student's parent: What is the best way to succeed as a CS student?

To be honest, most of the advice I give is not specific to a computer science major. At a first approximation, what it takes to succeed as a CS student is the same as what it takes to succeed as a student in any major: show up and do the work. But there are a few things a CS student does that are discipline-specific, most of which involve the tools we use.

I've decided to put together a list of suggestions that I can point our students to, and to which I can refer occasionally in order to refresh my mind. My advice usually includes one or all of these suggestions, with a focus on students at the beginning of our program:

  • Go to every class and every lab session. This is #0 because it should go without saying, but sometimes saying it helps. Students don't always have to go to their other courses every day in order to succeed.

  • Work steadily on a course. Do a little work on your course, both programming and reading or study, frequently -- every day, if possible. This gives your brain a chance to see patterns more often and learn more effectively. Cramming may help you pass a test, but it doesn't usually help you learn how to program or make software.

  • Ask your professor questions sooner rather than later. Send email. Visit office hours. This way, you get answers sooner and don't end up spinning your wheels while doing homework. Even worse, feeling confused can lead you to shying away from doing the work, which gets in the way of #1.

  • Get to know your programming environment. When programming in Python, simply feeling comfortable with IDLE, and with the file system where you store your programs and data, can make everything else seem easier. Your mind doesn't have to look up basic actions or worry about details, which enables you to make the most of your programming time: working on the assigned task.

  • Spend some of your study time with IDLE open. Even when you aren't writing a program, the REPL can help you! It lets you try out snippets of code from your reading, to see them work. You can run small experiments of your own, to see whether you understand syntax and operators correctly. You can make up your own examples to fill in the gaps in your understanding of the problem.

    Getting used to trying things out in the interactions window can be a huge asset. This is one of the touchstones of being a successful CS student.

That's what came to mind at the end of a Friday, at the end of a long week, when I sat down to give advice to one student. I'd love to hear your suggestions for improving the suggestions in my list, or other bits of advice that would help our students. Email me your ideas, and I'll make my list better for anyone who cares to read it.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

January 29, 2023 7:51 AM

A Thousand Feet of Computing

Cory Doctorow, in a recent New Yorker interview reminisces about learning to program. The family had a teletype and modem.

My mom was a kindergarten teacher at the time, and she would bring home rolls of brown bathroom hand towels from the kid's bathroom at school, and we would feed a thousand feet of paper towel into the teletype and I would get a thousand feet of computing after school at the end of the day.

Two things:

  • Tsk, tsk, Mom. Absconding with school supplies, even if for a noble cause! :-) Fortunately, the statute of limitations on pilfering paper hand towels has likely long since passed.

  • I love the idea of doing "a thousand feet of computing" each day. What a wonderful phrase. With no monitor, the teletype churns out paper for every line of code, and every line the code produces. You know what they say: A thousand feet a day makes a happy programmer.

The entire interview is a good read on the role of computing in modern society. The programmer in me also resonated with this quote from Doctorow's 2008 novel, Little Brother:

If you've never programmed a computer, there's nothing like it in the whole world. It's awesome in the truest sense: it can fill you with awe.

My older daughter recommended Little Brother to me when it first came out. I read many of her recommendations promptly, but for some reason this one sits on my shelf unread. (The PDF also sits in my to-read/ folder, unread.) I'll move it to the top of my list.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 18, 2023 2:46 PM

Prompting AI Generators Is Like Prompting Students

Ethan Mollick tells us how to generate prompts for programs like ChatGPT and DALL-E: give direct and detailed instructions.

Don't ask it to write an essay about how human error causes catastrophes. The AI will come up with a boring and straightforward piece that does the minimum possible to satisfy your simple demand. Instead, remember you are the expert and the AI is a tool to help you write. You should push it in the direction you want. For example, provide clear bullet points to your argument: write an essay with the following points: -Humans are prone to error -Most errors are not that important -In complex systems, some errors are catastrophic -Catastrophes cannot be avoided

But even the results from such a prompt are much less interesting than if we give a more explicit prompt. Fo instance, we might add:

use an academic tone. use at least one clear example. make it concise. write for a well-informed audience. use a style like the New Yorker. make it at least 7 paragraphs. vary the language in each one. end with an ominous note.

This reminds me of setting essay topics for students, either for long-form writing or for exams. If you give a bland uninteresting question, you will generally get a bland uninteresting answer. Such essays are hard to evaluate. A squooshy question allows the student to write almost anything in response. Students are usually unhappy in this scenario, too, because they don't know what you want them to write, or how they will be evaluated.

Asking a human a more specific question has downsides, though. It increases the cognitive load placed on them, because there are more things for them to be thinking about as they write. Is my tone right? Does this sound like the New Yorker? Did I produce the correct number of paragraphs? Is my essay factually accurate? (ChatGPT doesn't seem to worry about this one...) The tradeoff is clearer expectations. Many students prefer this trade, at least on longer form assignments when they have time to consider the specific requests. A good spec reduces uncertainty.

Maybe these AI programs are closer to human than we think after all. (Some people don't worry much about correctness either.)


On a related note: As I wrote elsewhere, I refuse to call ChatGPT or any program "an AI". The phrase "artificial intelligence" is not a term for a specific agent; it is the name of an idea. Besides, none of these programs are I yet, only A.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 15, 2023 12:07 PM

You Can Learn A Lot About People Just By Talking With Them

This morning on the exercise bike, I read a big chunk of Daniel Gross and Tyler Talk Talent, from the Conversations with Tyler series. The focus of this conversation is how to identify talent, as prelude to the release of their book on that topic.

The bit I've read so far has been like most Conversations with Tyler: interesting ideas with Cowen occasionally offering an offbeat idea seemingly for the sake of being offbeat. For example, if the person he is interviewing has read Shakespeare, he might say,

"Well, my hypothesis is that in Romeo and Juliet, Romeo and Juliet don't actually love each other at all. Does the play still make sense?" Just see what they have to say. It's a way of testing their second-order understanding of situations, diversity of characters.

This is a bit much for my taste, but the motivating idea behind talking to people about drama or literature is sound:

It's not something they can prepare for. They can't really fake it. If they don't understand the topic, well, you can switch to something else. But if you can't find anything they can understand, you figure, well, maybe they don't have that much depth or understanding of other people's characters.

It seems to me that this style of interviewing runs a risk of not being equitable to all candidates, and at the very least places high demands on both the interviewee and the interviewer. That said, Gross summarizes the potential value of talking to people about movies, music, and other popular culture in interviews:

I think that works because you can learn a lot from what someone says -- they're not likely to make up a story -- but it's also fun, and it is a common thing many people share, even in this era of HBO and Netflix.

This exchange reminded me of perhaps my favorite interview of all time, one in which I occupied the hot seat.

I was a senior in high school, hoping to study architecture at Ball State University. (Actual architecture... the software thing would come later.) I was a pretty good student, so I applied for Ball State's Whitinger Scholarship, one of the university's top awards. My initial application resulted in me being invited to campus for a personal interview. First, I sat to write an essay over the course of an hour, or perhaps half an hour. To be honest, I don't remember many details from that part of the day, only sitting in a room by myself for a while with a blue book and writing away. I wrote a lot of essays in those days.

Then I met with Dr. Warren Vander Hill, the director of the Honors College, for an interview. I'd had a few experiences on college campuses in the previous couple of years, but I still felt a little out of my element. Though I came from a home that valued reading and learning, my family background was not academic.

On a shelf behind Dr. Vander Hill, I noticed a picture of him in a Hope College basketball jersey, dribbling during a college game. I casually asked him about it and learned that he had played Division III varsity ball as an undergrad. I just now searched online in hopes of confirming my memory and learned that he is still #8 on the list of Hope's all-time career scoring leaders. I don't recall him slipping that fact into our chat... (Back then, he would have been #2!)

Anyway, we started talking basketball. Somehow, the conversation turned to Oscar Robertson, one of the NBA's all-time great players. He starred at Indianapolis's all-black Crispus Attucks High School and led the school to a state championship in 1955. From there, we talked about a lot of things -- the integration of college athletics, the civil rights movement, the state of the world in 1982 -- but it all seemed to revolve around basketball.

The time flew. Suddenly, the interview period was over, and I headed home. I enjoyed the conversation quite a bit, but on the hour drive, I wondered if I'd squandered my chances at the scholarship by using my interview time to talk sports. A few weeks later, though, I received a letter saying that I had been selected as one of the recipients.

That was the beginning of four very good years for me. Maybe I can trace some of that fortune to a conversation about sports. I certainly owe a debt to the skill of the person who interviewed me.

I got to know Dr. Vander Hill better over the next four years and slowly realized that he had probably known exactly what he was doing in that interview. He had found a common interest we shared and used it to start a conversation that opened up into bigger ideas. I couldn't have prepared answers for this conversation. He could see that I wasn't making up a story, that I was genuinely interested in the issues we were discussing and was, perhaps, genuinely interesting. The interview was a lot of fun, for both of us, I think, and he learned a lot about me from just talking.

I learned a lot from Dr. Vander Hill over the years, though what I learned from him that day took a few years to sink in.

Posted by Eugene Wallingford | Permalink | Categories: Managing and Leading, Personal, Teaching and Learning

January 10, 2023 2:20 PM

Are Major Languages' Parsers Implemented By Hand?

Someone on Mastodon posted a link to a 2021 survey of how the parsers for major languages are implemented. Are they written by hand, or automated by a parser generator? The answer was mixed: a few are generated by yacc-like tools (some of which were custom built), but many are written by hand, often for speed.

My two favorite notes:

Julia's parser is handwritten but not in Julia. It's in Scheme!

Good for the Julia team. Scheme is a fine language in which to write -- and maintain -- a parser.

Not only [is Clang's parser] handwritten but the same file handles parsing C, Objective-C and C++.

I haven't clicked through to the source code for Clang yet but, wow, that must be some file.

Finally, this closing comment in the paper hit close to the heart:

Although parser generators are still used in major language implementations, maybe it's time for universities to start teaching handwritten parsing?

I have persisted in having my compiler students write table-driven parsers by hand for over fifteen years. As I noted in this post at the beginning of the 2021 semester, my course is compilers for everyone in our major, or potentially so. Most of our students will not write another compiler in their careers, and traditional skills like implementing recursive descent and building a table-driven program are valuable to them more generally than knowing yacc or bison. Any of my compiler students who do eventually want to use a parser generator are well prepared to learn how, and they'll understand what's going on when they do, to boot.

My course is so old school that it's back to the forefront. I just had to be patient.

(I posted the seeds of this entry on Mastodon. Feel free to comment there!)

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

January 09, 2023 12:19 PM

Thoughts on Software and Teaching from Last Week's Reading

I'm trying to get back into the habit of writing here more regularly. In the early days of my blog, I posted quick snippets every so often. Here's a set to start 2023.

• Falsework

From A Bridge Over a River Never Crossed:

Funnily enough, traditional arch bridges were built by first having a wood framing on which to lay all the stones in a solid arch (YouTube). That wood framing is called falsework, and is necessary until the arch is complete and can stand on its own. Only then is the falsework taken away. Without it, no such bridge would be left standing. That temporary structure, even if no trace is left of it at the end, is nevertheless critical to getting a functional bridge.

Programmers sometimes write a function or an object that helps them build something else that they couldn't easily have built otherwise, then delete the bridge code after they have written the code they really wanted. A big step in the development of a student programmer is when they do this for the first time, and feel in their bones why it was necessary and good.

• Repair as part of the history of an object

From The Art of Imperfection and its link back to a post on making repair visible, I learned about Kintsugi, a practice in Japanese art...

that treats breakage and repair as part of the history of an object, rather than something to disguise.

I have this pattern around my home, at least on occasion. I often repair my backpack, satchel, or clothing and leave evidence of the repair visible. My family thinks it's odd, but figure it's just me.

Do I do this in code? I don't think so. I tend to like clean code, with no distractions for future readers. The closest thing to Kintsugi I can think of now are comments that mention where some bit of code came from, especially if the current code is not intuitive to me at the time. Perhaps my memory is failing me, though. I'll be on the watch for this practice as I program.

• "It is good to watch the master."

I've been reading a rundown of the top 128 tennis players of the last hundred years, including this one about Pancho Gonzalez, one of the great players of the 1940s, '50s, and '60s. He was forty years old when the Open Era of tennis began in 1968, well past his prime. Even so, he could still compete with the best players in the game.

Even his opponents could appreciate the legend in their midst. Denmark's Torben Ulrich lost to him in five sets at the 1969 US Open. "Pancho gives great happiness," he said. "It is good to watch the master."

The old masters give me great happiness, too. With any luck, I can give a little happiness to my students now and then.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Software Development, Teaching and Learning

January 05, 2023 12:15 PM

A Family of Functions from a Serendipitous Post, and Thoughts about Teaching

Yesterday, Ben Fulton posted on Mastodon:

TIL: C++ has a mismatch algorithm that returns the first non-equal pair of elements from two sequences. ...

C++'s mismatch was new to me, too, so I clicked through to the spec on cppreference.com to read a bit more. I learned that mismatch is an algorithm implemented as as a template function with several different signatures. My thoughts turned immediately to my spring course, Programming Languages, which starts with an introduction to Racket and functional programming. mismatch would make a great example or homework problem for my students, as they learn to work with Racket lists and functions! I stopped working on what I was doing and used the C++ spec to draw up a family of functions for my course:

    ; Return the first mismatching pair of elements from two lists.
    ; Compare using eq?.
    ;   (mismatch lst1 lst2)
    ; Compare using a given binary predicate comp?.
    ;   (mismatch comp? lst1 lst2)
    ; Compare using a given binary predicate comp?,
    ; as a higher-order function.
    ;   ((make-mismatch comp?) lst1 lst2)
    ; Return the first mismatching pair of elements from two ranges,
    ; also as a higher-order function.
    ; If last2 is not provided, it denotes first2 + (last1 - first1).
    ;   (make-mismatch first1 last1 first2 [last2]) -> (f lst1 lst2)

Of course, this list is not exhaustive, only a start. With so many related possibilities, mismatch will make a great family of examples or homework problems for the course! What a fun distraction from the other work in my backlog.

Ben's post conveniently arrived in the middle of an email discussion with the folks who teach our intro course, about ChatGPT and the role it will play in Intro. I mentioned ChatGPT in a recent post suggesting that we all think about tools like ChatGPT and DALL-E from the perspective of cultural adaptation: how do we live with new AI tools knowing that we change our world to accommodate our technologies? In that post, I mentioned only briefly the effect that these tools will have on professors, their homework assignments, and the way we evaluate student competencies and performance. The team preparing to teach Intro this spring has to focus on these implications now because they affect how the course will work. Do we want to mitigate the effects of ChatGPT and, if so, how?

I think they have decided mostly to take a wait-and-see approach this semester. We always have a couple of students who do not write their own code, and ChatGPT offers them a new way not to do so. When we think students have not written the code they submitted, we talk with them. In particular, we discuss the code and ask the student to explain or reason about it.

Unless the presence of ChatGPT greatly increases the number of students submitting code they didn't write, this approach should continue to work. I imagine we will be fine. Most students want to learn; they know that writing code is where they learn the most. I don't expect that access to ChatGPT is going to change the number of students taking shortcuts, at least not in large numbers. Let's trust our students as we keep a watchful eye out for changes in behavior.

The connection between mismatch and the conversation about teaching lies in the role that a family of related functions such as mismatch can play in building a course that is more resistant to the use of AI assistants in a way that harms student learning. I already use families of related function specs as a teaching tool in my courses, for purely pedagogical reasons. Writing different versions of the same function, or seeing related functions used to solve slightly different problems, is a good way to help students deepen understanding of an idea or to help them make connections among different concepts. My mismatches give me another way to help students in Programming Languages learn about processing lists, passing functions as arguments, returning functions as values, and accepting a variable number of arguments. I'm curious to see how this family of functions works for students.

A set of related functions also offers a tool both for helping professors determine whether students have learned to write code. We already ask students in our intro course to modify code. Asking students to convert a function with one spec into a function with a slightly different spec, like writing different versions of the same function, give them the chance benefit from their understanding the existing code. It is easier for a programmer to modify a function if they understand it. The existing code is a scaffold that enables the student to focus on the single feature or concept they need to write the new code.

Students who have not written code like the code they are modifying have a harder time reading and modifying the given code, especially when operating under any time or resource limitation. In a way, code modification exercises do something simpler to asking students to explain code to us: the modification task exposes when students don't understand code they claim to have written.

Having ChatGPT generate a function for you won't be as valuable if you will soon be asked to explain the code in detail or to modify the code in a way that requires you understand it. Increasing the use of modification tasks is one way to mitigate the benefits of a student having someone else write the code for them. Families of functions such as mismatch above are a natural source of modification tasks.

Beyond the coming semester, I am curious how our thinking about writing code will evolve in the presence of ChatGPT-like tools. Consider the example of auto-complete facilities in our editors. Few people these days think of using auto-complete as cheating, but when it first came out many professors were concerned that using auto-complete was a way for students not to learn function signatures and the details of standard libraries. (I'm old enough to still have a seed of doubt about auto-complete buried somewhere deep in my mind! But that's just me.)

If LLM-based tools become the new auto-complete, one level up from function signatures, then how we think about programming will probably change. Likewise how we think about teaching programming... or not. Did we change how we teach much as a result of auto-complete?

The existence of ChatGPT is a bit disconcerting for today's profs, but the long-term implications are kind of interesting.

In the meantime, coming across example generators like C++'s mismatch helps me deal with the new challenge and gives me unexpected fun writing code and problem descriptions.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

December 30, 2022 12:40 PM

What Can Universities Learn from Barnes & Noble's Surprising Turnaround?

A recent issue of Ted Gioia's newsletter asks, What can we learn from Barnes & Noble's surprising turnaround? In one sentence, the answer is:

If you want to sell books, you must love those books.

Perhaps we can apply Barnes & Noble's lesson to education.

If anything will save the mid-sized comprehensive university in the face of changing demographics and state funding, it will likely be this:

If you want to teach students, you must love both teaching and students.

Comprehensive universities (regional universities that focus on undergraduate education) are caught in the middle between large research-focused schools and small, mostly private schools. They try to offer the best of both worlds, without having the resources that buttress those other school's operation. The big research schools have external research funding, large media contracts for their athletics programs, and primacy of place in the minds of potential students. The small private schools offer the "small school experience", often to targeted audiences of students and often with considerable endowments and selective admissions that heighten the appeal.

Mid-sized comprehensives are unsung jewels in many states, but economic changes make it harder to serve their mission than it was forty or even twenty years ago. They don't have much margin for error. What are they to do? As Barnes & Noble is demonstrating, the key to success for a bookstore is to put books and readers first. For the comprehensives, the key to success is almost certainly to put students and teaching first.

Other lessons from the Barnes & Noble turnaround may help, too. For example, in tough economic times, universities tend to centralize resources and decision making, in the name of focus and efficiency. However, decentralization empowers those closest to the students to meet the needs of the students in each academic disciplines. When given the chance, faculty and staff in the academic departments need to take this responsibility seriously. But then, most faculty are at comprehensives precisely because they want to work with undergraduates. The key element to it all, though, is putting students and teaching first, and everything else second.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

December 22, 2022 1:21 PM

The Ability to Share Partial Results Accelerated Modern Science

This passage is from Lewis Thomas's The Lives of a Cell, in the essay "On Societies as Organisms":

The system of communications used in science should provide a neat, workable model for studying mechanisms of information-building in human society. Ziman, in a recent "Nature" essay, points out, "the invention of a mechanism for the systematic publication of fragments of scientific work may well have been the key event in the history of modern science." He continues:
A regular journal carries from one research worker to another the various ... observations which are of common interest. ... A typical scientific paper has never pretended to be more than another little piece in a larger jigsaw -- not significant in itself but as an element in a grander scheme. The technique of soliciting many modest contributions to the store of human knowledge has been the secret of Western science since the seventeenth century, for it achieves a corporate, collective power that is far greater than any one individual can exert [italics mine].

In the 21st century, sites like arXiv lowered the barrier to publishing and reading the work of other scientists further. So did blogs, where scientists could post even smaller, fresher fragments of knowledge. Blogs also democratized science, by enabling scientists to explain results for a wider audience and at greater length than journals allow. Then came social media sites like Twitter, which made it even easier for laypeople and scientists in other disciplines to watch -- and participate in -- the conversation.

I realize that this blog post quotes an essay that quotes another essay. But I would never have seen the Ziman passage without reading Lewis. Perhaps you would not have seen the Lewis passage without reading this post? When I was in college, the primary way I learned about things I didn't read myself was by hearing about them from classmates. That mode of sharing puts a high premium on having the right kind of friends. Now, blogs and social media extend our reach. They help us share ideas and inspirations, as well as helping us to collaborate on science.


I first mentioned The Lives of a Cell a couple of weeks ago, in If only ants watched Netflix.... This post may not be the last to cite the book. I find something quotable and worth further thought every few pages.

Posted by Eugene Wallingford | Permalink | Categories: General, Patterns, Teaching and Learning

December 11, 2022 9:09 AM

Living with AI in a World Where We Change the World to Accommodate Our Technologies

My social media feeds are full of ChatGPT screenshots and speculation these days, as they have been with LLMs and DALL-E and other machine learning-based tools for many months. People wonder what these tools will mean for writers, students, teachers, artists, and anyone who produces ordinary text, programs, and art.

These are natural concerns, given their effect on real people right now. But if you consider the history of human technology, they miss a bigger picture. Technologies often eliminate the need for a certain form of human labor, but they just as often create a new form of human labor. And sometimes, they increase the demand for the old kind of labor! If we come to rely on LLMs to generate text for us, where will we get the text with which to train them? Maybe we'll need people to write even more replacement-level prose and code!

As Robin Sloan reminds us in the latest edition of his newsletter, A Year of New Avenues, we redesign the world to fit the technologies we create and adopt.

Likewise, here's a lesson from my work making olive oil. In most places, the olive harvest is mechanized, but that's only possible because olive groves have been replanted to fit the shape of the harvesting machines. A grove planted for machine harvesting looks nothing like a grove planted for human harvesting.

Which means that our attention should be on how programs like GPT-2 might lead us to redesign the world we live and work in better to accommodate these new tools:

For me, the interesting questions sound more like
  • What new or expanded kinds of human labor might AI systems demand?
  • What entirely new activities do they suggest?
  • How will the world now be reshaped to fit their needs?
That last question will, on the timescale of decades, turn out to be the most consequential, by far. Think of cars ... and of how dutifully humans have engineered a world just for them, at our own great expense. What will be the equivalent, for AI, of the gas station, the six-lane highway, the parking lot?

Many professors worry that ChatGPT makes their homework assignments and grading rubrics obsolete, which is a natural concern in the short run. I'm old enough that I may not live to work in a world with the AI equivalent of the gas station, so maybe that world seems too far in the future to be my main concern. But the really interesting questions for us to ask now revolve around how tools such as these will lead us to redesign our worlds to accommodate and even serve them.

Perhaps, with a little thought and a little collaboration, we can avoid engineering a world for them at our own great expense. How might we benefit from the good things that our new AI technologies can provide us while sidestepping some of the highest costs of, say, the auto-centric world we built? Trying to answer that question is a better long-term use of our time and energy that fretting about our "Hello, world!" assignments and advertising copy.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 03, 2022 2:34 PM

Why Teachers Do All That Annoying Stuff

Most people, when they become teachers, tell themselves that they won't do all the annoying things that their teachers did. If they teach for very long, though, they almost all find themselves slipping back to practices they didn't like as a student but which they now understand from the other side of the fence. Dynomight has written a nice little essay explaining why. Like deadlines. Why have deadlines? Let students learn and work at their own pace. Grade what they turn in, and let them re-submit their work later to demonstrate their newfound learning.

Indeed, why not? Because students are clever and occasionally averse to work. A few of them will re-invent a vexing form of the ancient search technique "Generate and Test". From the essay:

  1. Write down some gibberish.
  2. Submit it.
  3. Make a random change, possibly informed by feedback on the last submission.
  4. Resubmit it. If the grade improved, keep it, otherwise revert to the old version.
  5. Goto 3.

You may think this is a caricature, but I see this pattern repeated even in the context of weekly homework assignments. A student will start early and begin a week-long email exchange where they eventually evolve a solution that they can turn in when the assignment is due.

I recognize that these students are responding in a rational way to the forces they face: usually, uncertainty and a lack of the basic understanding needed to even start the problem. My strategy is to try to engage them early on in the conversation in a way that helps them build that basic understanding and to quiet their uncertainty enough to make a more direct effort to solve the problem.

Why even require homework? Most students and teachers want for grades to reflect the student's level of mastery. If we eliminate homework, or make it optional, students have the opportunity to demonstrate their mastery on the final exam or final project. Why indeed? As the essay says:

But just try it. Here's what will happen:
  1. Like most other humans, your students will be lazy and fallible.
  2. So many of them will procrastinate and not do the homework.
  3. So they won't learn anything.
  4. So they will get a terrible grade on the final.
  5. And then they will blame you for not forcing them to do the homework.

Again, the essay is written in a humorous tone that exaggerates the foibles and motivations of students. However, I have been living a variation of this pattern in my compilers course over the last few years. Here's how things have evolved.

I assign the compiler project as six stages of two weeks each. At the end of the semester, I always ask students for ways I might improve the course. After a few years teaching the course, students began to tell me that they found themselves procrastinating at the start of each two-week cycle and then having to scramble in the last few days to catch up. They suggested I require future students to turn something in at the end of the first week, as a way to get them started working sooner.

I admired their self-awareness and added a "status check" at the midpoint of each two-week stage. The status check was not to be graded, but to serve as a milepost they could aim for in completing that cycle's work. The feedback I provided, informal as it was, helped them stay course, or get back on course, if they had missed something important.

For several years, this approach worked really well. A few teams gamed the system, of course (see generate-and-test above), but by and large students used the status checks as intended. They were able to stay on track time-wise and to get some early feedback that helped them improve their work. Students and professor alike were happy.

Over the last couple of years, though, more and more teams have begun to let the status checks slide. They are busy, overburdened in other courses or distracted by their own projects, and ungraded work loses priority. The result is exactly what the students who recommended the status checks knew would happen: procrastination and a mad scramble in the last few days of the stage. Unfortunately, this approach can lead a team to fall farther and farther behind with each passing stage. It's hard to produce a complete working compiler under these conditions.

Again, I recognize that students usually respond in a rational way to the forces they face. My job now is to figure out how we might remove those forces, or address them in a more productive way. I've begun thinking about alternatives, and I'll be debriefing the current offering of the course with my students over the next couple of weeks. Perhaps we can find something that works better for them.

That's certainly my goal. When a team succeeds at building a working compiler, and we use it to compile and run an impressive program -- there's no feeling quite as joyous for a programmer, or a student, or a professor. We all want that feeling.

Anyway, check out the full essay for an entertaining read that also explains quite nicely that teachers are usually responding in a rational way to the forces they face, too. Cut them a little slack.

Posted by Eugene Wallingford | Permalink | Categories: Managing and Leading, Patterns, Teaching and Learning

November 20, 2022 9:00 AM

Beautiful Ideas Deserve Beautiful Presentation

From Matthew Butterick, of Beautiful Racket fame:

I always think about—and encourage others to think about—how design and typography can complement the underlying object by finding a way to communicate its virtues. If your writing contains beautiful ideas, then your presentation of that writing should be likewise beautiful.

I am old-fashioned, perhaps, in feeling this way about software. A program that embodies beautiful ideas should itself be beautifully designed, and beautifully presented. The universe calls us in this direction.

The above passage comes from a charming essay on how Butterick ended up living a life of typography, in addition to his skills as a programmer and a lawyer. Spoiler: the title "Power, Corruption & Lies" refers not to any political intrigue but to an album by the rock band New Order.

Butterick is also one of the principals pursuing action against GitHub Copilot for violating the terms of the open-source licenses on the software it mined to build the tool. Sometimes, programmers have to deal with things less beautiful than the code we like to write, in order to protect that code and its creators.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

October 30, 2022 9:32 AM


From Robin Sloan Sloan's newsletter:

There was a book I wanted very badly to write; a book I had been making notes toward for nearly ten years. (In my database, the earliest one is dated December 13, 2013.) I had not, however, set down a single word of prose. Of course I hadn't! Many of you will recognize this feeling: your "best" ideas are the ones you are most reluctant to realize, because the instant you begin, they will drop out of the smooth hyperspace of abstraction, apparate right into the asteroid field of real work.

I can't really say that there is a book I want very badly to write. In the early 2000s I worked with several colleagues on elementary patterns, and we brainstormed writing an intro CS textbook built atop a pattern language. Posts from the early days of this blog discuss some of this work from ChiliPLoP, I think. I'm not sure that such a textbook could ever have worked in practice, but I think writing it would have been a worthwhile experience anyway, for personal growth. But writing such a book takes a level of commitment that I wasn't able to make.

That experience is one of the reasons I have so much respect for people who do write books.

While I do not have a book for which I've been making notes in recent years, I do recognize the feeling Sloan describes. It applies to blog posts and other small-scale writing. It also applies to new courses one might create, or old courses one might reorganize and teach in a very different way.

I've been fortunate to be able to create and re-create many courses over my career. I also have some ideas that sit in the back of my mind because I'm a little concerned about the commitment they will require, the time and the energy, the political wrangling. I'm also aware that the minute I begin to work on them, they will no longer be perfect abstractions in my mind; they will collide with reality and require compromises and real work.

(TIL I learned the word "apparate". I'm not sure how I feel about it yet.)

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Personal, Teaching and Learning

October 23, 2022 9:54 AM

Here I Go Again: Carmichael Numbers in Graphene

I've been meaning to write a post about my fall compilers course since the beginning of the semester but never managed to set aside time to do anything more than jot down a few notes. Now we are at the end of Week 9 and I just must write. Long-time readers know what motivates me most: a fun program to write in my student's source language!

TFW you run across a puzzle and all you want to do now is write a program to solve it. And teach your students about the process.
-- https://twitter.com/wallingf/status/1583841233536884737

Yesterday, it wasn't a puzzle so much as discovering a new kind of number, Carmichael numbers. Of course, I didn't discover them (neither did Carmichael, though); I learned of them from a Quanta article about a recent proof about these numbers that masquerade as primes. One way of defining this set comes from Korselt:

A positive composite integer n is a Carmichael number if and only if it has multiple prime divisors, no prime divisor repeats, and for each prime divisor p, p-1 divides n-1.

This definition is relatively straightforward, and I quickly imagined am imperative solution with a loop and a list. The challenge of writing a program to verify a number is a Carmichael number in my compiler course's source language is that it has neither of these things. It has no data structures or even local variables; only basic integer and boolean arithmetic, if expressions, and function calls.

Challenge accepted. I've written many times over the years about the languages I ask my students to write compilers for and about my adventures programming in them, from Twine last year through Flair a few years ago to a recurring favorite, Klein, which features prominently in popular posts about Farey sequences and excellent numbers.

This year, I created a new language, Graphene, for my students. It is essentially a small functional subset of Google's new language Carbon. But like it's predecessors, it is something of an integer assembly language, fully capable of working with statements about integers and primes. Korselt's description of Carmichael numbers is right in Graphene's sweet spot.

As I wrote in the post about Klein and excellent numbers, my standard procedure in cases like this is to first write a reference program in Python using only features available in Graphene. I must do this if I hope to debug and test my algorithm, because we do not have a working Graphene compiler yet! (I'm writing my compiler in parallel with my students, which is one of the key subjects in my phantom unwritten post.) I was proud this time to write my reference program in a Graphene-like subset of Python from scratch. Usually I write a Pythonic solution, using loops and variables, as a way to think through the problem, and then massage that code down to a program using a limited set of concepts. This time, I started with short procedural outline:

    # walk up the primes to n
    #   - find a prime divisor p:
    #     - test if a repeat         (yes: fail)
    #     - test if p-1 divides n-1  (no : fail)
    # return # prime divisors > 1
and then implemented it in a single recursive function. The first few tests were promising. My algorithm rejected many small numbers not in the set, and it correctly found 561, the smallest Carmichael number. But when I tested all the numbers up to 561, I saw many false positives. A little print-driven debugging found the main bug: I was stopping too soon in my search for prime divisors, at sqrt(n), due to some careless thinking about factors. Once I fixed that, boom, the program correctly handled all n up to 3000. I don't have a proof of correctness, but I'm confident the code is correct. (Famous last words, I know.)

As I tested the code, it occurred to me that my students have a chance to one-up standard Python. Its rather short standard stack depth prevented my program from reaching even n=1000. When I set sys.setrecursionlimit(5000), my program found the first five Carmichael numbers: 561, 1105, 1729, 2465, and 2821. Next come 6601 and 8911; I'll need a lot more stack frames to get there.

All those stack frames are unnecessary, though. My main "looping" function is beautifully tail recursive: two failure cases, the final answer case checking the number of prime divisors, and two tail-recursive calls that move either to the next prime as potential factor or to the next quotient when we find one. If my students implement proper tail calls -- an optimization that is optional in the course but encouraged by their instructor with gusto -- then their compiler will enable us to solve for values up to the maximum integer in the language, 231-1. We'll be limited only by the speed of the target language's VM, and the speed of the target code the compiler generates. I'm pretty excited.

Now I have to resist the urge to regale my students with this entire story, and with more details about how I approach programming in a language like Graphene. I love to talk shop with students about design and programming, but our time is limited... My students are already plenty busy writing the compiler that I need to run my program!

This lark resulted in an hour or so writing code in Python, a few more minutes porting to Graphene, and an enjoyable hour writing this blog post. As the song says, it was a good day.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

July 31, 2022 8:54 AM

Caring about something whittles the world down to a more manageable size

In The Orchid Thief, there is a passage where author Susan Orlean describes a drive across south Florida on her way to a state preserve, where she'll be meeting an orchid hunter. She ends the passage this way:

The land was marble-smooth and it rolled without a pucker to the horizon. My eyes grazed across the green band of ground and the blue bowl of sky and then lingered on a dead tire, a bird in flight, an old fence, a rusted barrel. Hardly any cars came toward me, and I saw no one in the rearview mirror the entire time. I passed so many vacant acres and looked past them to so many more vacant acres and looked ahead and behind at the empty road and up at the empty sky; the sheer bigness of the world made me feel lonely to the bone. The world is so huge that people are always getting lost in it. There are too many ideas and things and people, too many directions to go. I was starting to believe that the reason it matters to care passionately about something is that it whittles the world down to a more manageable size. It makes the world seem not huge and empty but full of possibility. If I had been an orchid hunter I wouldn't have see this space as sad-making and vacant--I think I would have seen it as acres of opportunity where the things I loved were waiting to be found.

John Laroche, the orchid hunter at the center of The Orchid Thief, comes off as obsessive, but I think many of us know that condition. We have found an idea or a question or a problem that grabs our attention, and we work on it for years. Sometimes, we'll follow a lead so far down a tunnel that it feels a lot like the swamps Laroche braves in search of the ghost orchid.

Even a field like computer science is big enough that it can feel imposing if a person doesn't have a specific something to focus their attention and energy on. That something doesn't have to be forever... Just as Laroche had cycled through a half-dozen obsessions before turning his energy to orchids, a computer scientist can work deeply in an area for a while and then move onto something else. Sometimes, there is a natural evolution in the problems one focuses on, while other times people choose to move into a completely different sub-area. I see a lot of people moving into machine learning these days, exploring how it can change the sub-field they used to focus exclusively on.

As a prof, I am fortunate to be able to work with young adults as they take their first steps in computer science. I get to watch many of them find a question they want to answer, a problem they want to work on for a few years, or an area they want to explore in depth until they master it. It's also sad, in a way, to work with a student who never quite finds something that sparks their imagination. A career in software, or anything, really, can look as huge and empty as Orlean's drive through south Florida if someone doesn't care deeply about something. When they do, the world seems not huge and empty, but full of possibility.

I'm about halfway through The Orchid Thief and am quite enjoying it.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

July 28, 2022 11:48 AM

A "Teaching with Patterns" Workshop

the logo of PLoP 2022, a red block with block letters, PLoP in white and 2022 in black

Yesterday afternoon I attended a Teaching with Patterns workshop that is part of PLoP 2022.

When the pandemic hit in 2020, PLoP went virtual, as did so many conferences. It was virtual last year and will be again this year as well. On the spur of the moment, I attended a couple of the 2020 keynote talks online. Without a real commitment to the conference, though I let my day-to-day teaching and admin keep me from really participating. (You may recall that I did it right for StrangeLoop last year, as evidenced by several blog posts ending here.)

When I peeked in on PLoP virtually a couple of years ago, it had already been too many years away from my last PLoP, which itself came after too many years away! Which is to say: I miss PLoP and my friends and colleagues in the software patterns world.

PLoP 2022 itself is in October. Teaching with Patterns was a part of PLoPourri, a series of events scheduled throughout the year in advance of the conference proper. It was organized by Michael Weiss of Carleton University in Ottawa, a researcher on open source software.

Upon joining the Zoom session for the workshop, I was pleased to see Michael, a colleague I first met at PLoP back in the 1990s, and Pavel Hruby, whom I met at one of the first ChiliPLoPs many years ago. There were a handful of other folks participating, too, bringing experience from a variety of domains. One, Curt McNamara, has significant experience using patterns in his course on sustainable graphic design.

The workshop was a relaxed affair. First, participants shared their experiences teaching with patterns. Then we all discussed our various approaches and shared lessons we have learned. Michael gave a few opening remarks and then asked four questions to prime the conversation:

  • How do you use patterns when you teach a topic?
  • What format do you use to teach with patterns?
  • Do you teach with your own or existing patterns?
  • What works best/worst?
He gave us a few minutes to think about our answers and to post anything we liked to the workshop's whiteboard.

My answers may sound familiar to anyone who has read my blog long enough to hear me talk about the courses I teach and, going way back, to my work at PLoP and ChiliPLoP.

I use patterns to teach design techniques and trade-offs. It's easy to to lecture students on particular design solutions, but that's not very effective at helping students learn how to do design, to make choices based on the forces at play in any given problem. Patterns help me to think about the context in which a technique applies, the tradeoffs it helps us to make, and the state of their solution.

I rarely have students read patterns themselves, at least in one of the stylized pattern forms. Instead, I integrate the patterns into the stories I tell, into the conversations I have with my students about problems and solutions, and finally into the session notes I write up for them and me.

These days, I mostly teach courses on programming languages and compilers. I have written my own patterns for the programming languages course and use them to structure two units, on structurally recursive programming and closures for managing state. I've long dreamed of writing more patterns for the compiler course, which seems primed for the approach: So many of the structures we build when writing a compiler are the result of decades of experience, with tradeoffs that are often left implicit in textbooks and in the heads of experts.

I have used my own patterns as well as patterns from the literature when teaching other courses as well, back in the days when I taught three courses a semester. When I taught knowledge-based systems every year, I used patterns that I wrote to document the "generic task" approach to KBS in which my work lived. In our introductory OOP courses, I tended to use patterns from the literature both as a way to teach design techniques and trade-offs and as way to prepare students to graduate into a world where OO design patterns were part of the working vocabulary.

I like how patterns help me discuss code with students and how they help me evaluate solutions -- and communicate how I evaluate solutions.

That is more information than I shared yesterday... This was only a one and a half-hour workshop, and all of the participants had valuable experience to share.

I didn't take notes on what others shared or on the conversations that followed, but I did note a couple of things in general. Several people use a set of patterns or even a small pattern language to structure their entire course. I have done this at the unit level of a course, never at the scale of the course. My compiler course would be a great candidate here, but doing so would require that I write a lot of new material to augment and replace some of what I have now.

Likewise, a couple of participants have experimented with asking students to write patterns themselves. My teaching context is different than theirs, so I'm not sure this is something that can work for me in class. I've tried it a time or two with master's-level students, though, and it was educational for both the student and me.

I did grab all the links posted in the chat room so that I can follow up on them to read more later:

I also learned one new tech thing at the workshop: Padlet, a real-time sharing platform that runs in the browser. Michael used a padlet as the workshop's whiteboard, in lieu of Zoom's built-in tool (which I've still never used). The padlet made it quite straightforward to make and post cards containing text and other media. I may look into it as a classroom tool in the future.

Padlet also made it pretty easy to export the whiteboard in several formats. I grabbed a PDF copy of the workshop whiteboard for future reference. I considered linking to that PDF here, but I didn't get permission from the group first. So you'll just have to trust me.

Attending this workshop reminded me that I do not get to teach enough, at least not formal classroom teaching, and I miss it! As I told Michael in a post-workshop thank-you e-mail:

That was great fun, Michael. Thanks for organizing! I learned a few things, but mostly it is energizing simply to hear others talk about what they are doing.
"Energizing" really is a good word for what I experienced. I'm hyped to start working in more detail on my fall course, which starts in less than four weeks.

I'm also energized to look into the remaining PLoPourri events between now and the conference. (I really wish now that I had signed up for The Future of Education workshop in May, which was on "patterns for reshaping learning and the campus".) PLoP itself is on a Monday this year, in late October, so there is a good chance I can make it as well.

I told Michael that Teaching with Patterns would be an excellent regular event at PLoP. He seemed to like that thought. There is a lot of teaching experience out there to be shared -- and a lot of energy to be shared as well.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Teaching and Learning

July 03, 2022 9:00 AM

The Difference Between Medicine and Being a Doctor Is Like ...

Morgan Housel's recent piece on experts trying too hard includes a sentence that made me think of what I teach:

A doctor once told me the biggest thing they don't teach in medical school is the difference between medicine and being a doctor — medicine is a biological science, while being a doctor is often a social skill of managing expectations, understanding the insurance system, communicating effectively, and so on.

Most of the grads from our CS program go on to be software developers or to work in software-adjacent jobs like database administrator or web developer. Most of the rest work in system administration or networks. Few go on to be academic computer scientists. As Housel's doctor knows about medicine, there is a difference between academic computer science and being a software developer.

The good news is, I think the CS profs at many schools are aware of this, and the schools have developed computer science programs that at least nod at the difference in their coursework. The CS program at my school has a course on software engineering that is more practical than theoretical, and another short course that teaches practical tools such as version control, automated testing, and build tools, and skills such as writing documentation. All of our CS majors complete a large project course in which students work in teams to create a piece of software or a secure system, and the practical task of working as a team to deliver a piece of working software is a focus of the course. On top of those courses, I think most of our profs try to keep their courses real for students they know will want to apply what they learn in Algorithms, say, or Artificial Intelligence in their jobs as developers.

Even so, there is always a tension in classes between building foundational knowledge and building practical skills. I encounter this tension in both Programming Languages and Translation of Programming Languages. There are a lot of cool things we could learn about type theory, some of which might turn out to be quite useful in a forty-year career as a developer. But any time we devote to going deeper on type theory is time we can't devote to the concrete languages skills of a software developer, such as learning and creating APIs or the usability of programming languages.

So, we CS profs have to make design trade-offs in our courses as we try to balance the forces of students learning computer science and students becoming software developers. Fortunately, we learn a little bit about recognizing, assessing, and making trade-offs in our work both as computer scientists and as programmers. That doesn't make it easy, but at least we have some experience for thinking about the challenge.

The sentence quoted above reminds me that other disciplines face a similar challenge. Knowing computer science is different from being a software developer, or sysadmin. Knowing medicine is different from being a doctor. And, as Housel explains so well in his own work, knowing finance is different from being an investor, which is usually more about psychology and self-awareness than it is about net present value or alpha ratios. (The current stock market is a rather harsh reminder of that.)

Thanks to Housel for the prompt. The main theme of his piece — that experts makes mistakes that novices can't make, which leads to occasional unexpected outcomes — is the topic for another post.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

May 24, 2022 4:09 PM

Observing Students Learn to REPL in Dr. Racket

I recently ran across an old post by @joepolitz, Beginner REPL Stumbles, that records some of the ways he has observed students struggle as they learn to use IDEs with REPLs and files. As I mentioned on Twitter, it struck a chord with me even though I don't teach beginning programmers much these days. My tweets led to a short conversation that I'd like to record, and slightly expoand on, here.

I've noticed the first of the struggles in my junior-level Programming Languages class: students not knowing, or not taking seriously enough, the value of ctrl-up to replay and edit a previous interaction. If students cannot work effectively in the REPL, they will resort to typing all of their code in the definitions pane and repeatedly re-running it. This programming style misses out on the immense value of the REPL as a place to evolve code rapidly, with continual feedback, on the way to becoming a program.

As recommended in the post, I now demonstrate ctrl-up early in the course and note whenever I use it in a demo. If a student finds that their keyboard maps ctrl-up to another behavior, I show them how to define a shortcut in Preferences. This simple affordance can have an inordinate effect on the student's programming experience.

The other observations that Politz describes may be true for my students, too, and I just don't see them. My students are juniors and seniors who already have a year of experience in Python and perhaps a semester using Java. We aren't in the lab together regularly. I usually hear about their struggles with content when they ask questions, and when they do, they don't usually ask about process or tools. Sometimes, they will demo some interaction for me and I'll get to see an unexpected behavior in usage and help them, but that's rare.

(I do recall a student coming into my office once a few years ago and opening up a source file -- in Word. They said they had never gotten comfortable with Dr. Racket and that Word helped them make progress typing and editing code faster. We talked about ways to learn and practice Dr. Racket, but I don't think they ever switched.)

Having read about some of the usage patterns that Politz reports, I think I need to find ways to detect misunderstandings and difficulties with tools sooner. The REPL, and the ability to evolve code from interactions in the REPL into programs in the definitions pane, are powerful tools -- if one groks them and learns to use them effectively. As Politz notes, direct instruction is a necessary antidote to address these struggles. Direct instruction up front may also help my students get off to a better start with the tools.

There is so much room for improvement hidden inside assumptions that are baked into our current tools and languages. Observing learners can expose things we never think about, if we pay attention. I wonder what else I have been missing...

Fortunately, both Joe Politz and Shriram Krishnamurthi encountered my tweets. Krishnamurthi provided helpful context, noting that the PLT Scheme team noticed many of these issues in the early days of Dr. Scheme. They noticed others while running teacher training sessions for @Bootstrapworld. In both cases, instructors were in the lab with learners while they used the tools. In the crush to fix more pressing problems, the interaction issues went unaddressed. In my experience, they are also subtle and hard to appreciate fully without repeated exposure.

Politz provided a link to a workshop paper on Repartee, a tool that explicitly integrates interactive programming and whole-program editing. Very cool. As Krishnamurthi noted to close the conversation, Repartee demonstrates that we may be able to do better than simply teach students to use a REPL more effectively. Perhaps we can make better tools.

I've been learning a lot about CS education research the last few years. It is so much more than the sort of surface-level observations and uncontrolled experiments I saw, and made, at the beginning of my career. This kind of research demands a more serious commitment to science but offers the potential of real improvement in return for the effort. I'm glad to know CS ed researchers are making that commitment. I hope to help where I can.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

April 16, 2022 2:32 PM

More Fun, Better Code: A Bug Fix for my Pair-as-Set Implementation

In my previous post, I wrote joyously of a fun bit of programming: implementing ordered pairs using sets.

Alas, there was a bug in my solution. Thanks to Carl Friedrich Bolz-Tereick for finding it so quickly:

Heh, this is fun, great post! I wonder what happens though if a = b? Then the set is {{a}}. first should still work, but would second fail, because the set difference returns the empty set?

Carl Friedrich had found a hole in my small set of tests, which sufficed for my other implementations because the data structures I used separate cells for the first and second parts of the pair. A set will do that only if the first and second parts are different!

Obviously, enforcing a != b is unacceptable. My first code thought was to guard second()'s behavior:

    if my formula finds a result
       then return that result
       else return (first p)

This feels like a programming hack. Furthermore, it results in an impure implementation: it uses a boolean value and an if expression. But it does seem to work. That would have to be good enough unless I could find a better solution.

Perhaps I could use a different representation of the pair. Helpfully, Carl Friedrich followed up with pointers to several blog posts by Mark Dominus from last November that looked at the set encoding of ordered pairs in some depth. One of those posts taught me about another possibility: Wiener pairs. The idea is this:

    (a,b) = { {{a},∅}, {{b}} }

Dominus shows how Wiener pairs solve the a == b edge case in Kuratowski pairs, which makes it a viable alternative.

Would I ever have stumbled upon this representation, as I did onto the Kuratowski pairs? I don't think so. The representation is more complex, with higher-order sets. Even worse for my implementation, the formulas for first() and second() are much more complex. That makes it a lot less attractive to me, even if I never want to show this code to my students. I myself like to have a solid feel for the code I write, and this is still at the fringe of my understanding.

Fortunately, as I read more of Dominus's posts, I found there might be a way to save my Kuratowski-style solution. It turns out that the if expression I wrote above parallels the set logic used to implement a second() accessor for Kuratowski pairs: a choice between the set that works for a != b pairs and a fallback to a one-set solution.

From this Dominus post, we see the correct set expression for second() is:

the correct set expression for the second() function

... which can be simplified to:

an expression for the second() function simplified to a logical statement

The latter expression is useful for reasoning about second(), but it doesn't help me implement the function using set operations. I finally figured out what the former equation was saying: if (∪ p) is same as (∩ p), then the answer comes from (∩ p); otherwise, it comes from their difference.

I realized then that I could not write this function purely in terms of set operations. The computation requires the logic used to make this choice. I don't know where the boundary lies between pure set theory and the logic in the set comprehension, but a choice based on a set-empty? test is essential.

In any case, I think I can implement the my understanding of the set expression for second() as follows. If we define union-minus-intersection as:

    (set-minus (apply set-union aSet)
               (apply set-intersect aSet))
    (second p) = (if (set-empty? union-minus-intersection)
                     (set-elem (apply set-intersect aSet))
                     (set-elem union-minus-intersection))

The then clause is the same as the body of first(), which must be true: if the union of the sets is the same as their intersection, then the answer comes from the interesection, just as first()'s answer does.

It turns out that this solution essentially implements my first code idea above: if my formula from the previous blog entry finds a result, then return that result. Otherwise, return first(p). The circle closes.

Success! Or, I should: Success!(?) After having a bug in my original solution, I need to stay humble. But I think this does it. It passes all of my original tests as well as tests for a == b, which is the main edge case in all the discussions I have now read about set implementations of pairs. Here is a link to the final code file, if you'd like to check it out. I include the two simple test scenarios, for both a == b and a == b, as Rackunit tests.

So, all in all, this was a very good week. I got to have some fun programming, twice. I learned some set theory, with help from a colleague on Twitter. I was also reacquainted with Mark Dominus's blog, the RSS feed for which I had somehow lost track of. I am glad to have it back in my newsreader.

This experience highlights one of the selfish reasons I like for students to ask questions in class. Sometimes, they lead to learning and enjoyment for me as well. (Thanks, Henry!) It also highlights one of the reasons I like Twitter. The friends we make there participate in our learning and enjoyment. (Thanks, Carl Friedrich!)

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Teaching and Learning

April 13, 2022 2:27 PM

Programming Fun: Implementing Pairs Using Sets

Yesterday's session of my course was a quiz preceded by a fun little introduction to data abstraction. As part of that, I use a common exercise. First, I define a simple API for ordered pairs: (make-pair a b), (first p), and (second p). Then I ask students to brainstorm all the ways that they could implement the API in Racket.

They usually have no trouble thinking of the data structures they've been using all semester. Pairs, sure. Lists, yes. Does Racket have a hash type? Yes. I remind my students about vectors, which we have not used much this semester. Most of them haven't programmed in a language with records yet, so I tell them about structs in C and show them Racket's struct type. This example has the added benefit of seeing that Racket generates constructor and accessor functions that do the work for us.

The big payoff, of course, comes when I ask them about using a Racket function -- the data type we have used most this semester -- to implement a pair. I demonstrate three possibilities: a selector function (which also uses booleans), message passaging (which also uses symbols), and pure functions. Most students look on these solutions, especially the one using pure functions, with amazement. I could see a couple of them actively puzzling through the code. That is one measure of success for the session.

This year, one student asked if we could use sets to implement a pair. Yes, of course, but I had never tried that... Challenge accepted!

While the students took their quiz, I set myself a problem.

The first question is how to represent the pair. (make-pair a b) could return {a, b}, but with no order we can't know which is first and which is second. My students and I had just looked at a selector function, (if arg a b), which can distinguish between the first item and the second. Maybe my pair-as-set could know which item is first, and we could figure out the second is the other.

So my next idea was (make-pair a b){{a, b}, a}. Now the pair knows both items, as well as which comes first, but I have a type problem. I can't apply set operations to all members of the set and will have to test the type of every item I pull from the set. This led me to try (make-pair a b){{a}, {a, b}}. What now?

My first attempt at writing (first p) and (second p) started to blow up into a lot of code. Our set implementation provides a way to iterate over the members of a set using accessors named set-elem and set-rest. In fine imperative fashion, I used them to start whacking out a solution. But the growing complexity of the code made clear to me that I was programming around sets, but not with sets.

When teaching functional programming style this semester, I have been trying a new tactic. Whenever we face a problem, I ask the students, "What function can help us here?" I decided to practice what I was preaching.

Given p = {{a}, {a, b}}, what function can help me compute the first member of the pair, a? Intersection! I just need to retrieve the singleton member of ∩ p:

    (first p) = (set-elem (apply set-intersect p))

What function can help me compute the second member of the pair, b? This is a bit trickier... I can use set subtraction, {a, b} - {a}, but I don't know which element in my set is {a, b} and which is {a}. Serendipitously, I just solved the latter subproblem with intersection.

Which function can help me compute {a, b} from p? Union! Now I have a clear path forward: (∪ p) – (∩ p):

    (second p) = (set-elem
                   (set-minus (apply set-union p)
                              (apply set-intersect p)))

I implemented these three functions, ran the tests I'd been using for my other implementations... and they passed. I'm not a set theorist, so I was not prepared to prove my solution correct, but the tests going all green gave me confidence in my new implementation.

Last night, I glanced at the web to see what other programmers had done for this problem. I didn't run across any code, but I did find a question and answer on the mathematics StackExchange that discusses the set theory behind the problem. The answer refers to something called "the Kuratowski definition", which resembles my solution. Actually, I should say that my solution resembles this definition, which is an established part of set theory. From the StackExchange page, I learned that there are other ways to express a pair as a set, though the alternatives look much more complex. I didn't know the set theory but stumbled onto something that works.

My solution is short and elegant. Admittedly, I stumbled into it, but at least I was using the tools and thinking patterns that I've been encouraging my students to use.

I'll admit that I am a little proud of myself. Please indulge me! Department heads don't get to solve interesting problems like this during most of the workday. Besides, in administration, "elegant" and "clever" solutions usually backfire.

I'm guessing that most of my students will be unimpressed, though they can enjoy my pleasure vicariously. Perhaps the ones who were actively puzzling through the pure-function code will appreciate this solution, too. And I hope that all of my students can at least see that the tools and skills they are learning will serve them well when they run into a problem that looks daunting.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Teaching and Learning

March 16, 2022 2:52 PM

A Cool Project For Manipulating Images, Modulo Wordle

Wordle has been the popular game du jour for a while now. Whenever this sort of thing happens, CS profs think, "How can I turn this into an assignment?" I've seen a lot of discussion of ways to create a Wordle knock-off assignment for CS 1. None of this conversation has interested me much. First, I rarely teach CS 1 these days, and a game such as Wordle doesn't fit into the courses I do teach right now. Second, there's a certain element of Yogi Berra wisdom driving me away from Wordle: "It's so popular; no one goes there any more."

Most important, I had my students implementing Mastermind in my OO course back in the 2000-2005 era. I've already had most of the fun I can have with this game as an assignment. And it was a popular one with students, though challenging. The model of the game itself presents challenges for representation and algorithm, and the UI has the sort of graphic panache that tends to engage students. I remember receiving email from a student who had transferred to another university, asking me if I would still help her debug and improve her code for the assignment; she wanted to show it to her family. (Of course I helped!)

However I did see something recently that made me think of a cool assignment: 5x6 Art, a Twitter account that converts paintings and other images into minimalist 5 block-by-6 block abstract grids. The connection to Wordle is in the grid, but the color palette is much richer. Like any good CS prof, I immediately asked myself, "How can I turn this into an assignment?"

a screen capture of 5x6art from Twitter

I taught our intro course using the media computation approach popularized by Mark Guzdial back in 2006. In that course, my students processed images such as the artwork displayed above. They would have enjoyed this challenge! There are so many cool ways to think about creating a 5x6 abstraction of an input image. We could define a fixed palette of n colors, then map the corresponding region of the image onto a single block. But how to choose the color?

We could compute the average pixel value of the range and then choose the color in the palette closest to that value. Or we could create neighborhoods of different sizes around all of the palette colors so that we favor some colors for the grid over others. What if we simply compute the average pixel for the region and use that as the grid color? That would give us a much larger but much less distinct set of possible colors. I suspect that this would produce less striking outputs, but I'd really like to try the experiment and see the grids it produces.

What if we allowed ourselves a bigger grid, for more granularity in our output images? There are probably many other dimensions we could play with. The more artistically inclined among you can surely think of interesting twists I haven't found yet.

That's some media computation goodness. I may assign myself to teach intro again sometime soon just so that I can develop and use this assignment. Or stop doing other work for a day or two and try it out on my own right now.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 03, 2022 2:22 PM

Knowing Context Gives You Power, Both To Choose And To Make

We are at the point in my programming languages course where my students have learned a little Racket, a little functional programming, and a little recursive programming over inductive datatypes. Even though I've been able to connect many of the ideas we've studied to programming tasks out in the world that they care about themselves, a couple of students have asked, "Why are we doing this again?"

This is a natural question, and one I'm asked every time I teach this course. My students think that they will be heading out into the world to build software in Java or Python or C, and the ideas we've seen thus far seem pretty far removed from the world they think they will live in.

These paragraphs from near the end of Chelsea Troy's 3-part essay on API design do a nice job of capturing one part of the answer I give my students:

This is just one example to make a broader point: it is worthwhile for us as technologists to cultivate knowledge of the context surrounding our tools so we can make informed decisions about when and how to use them. In this case, we've managed to break down some web request protocols and build their pieces back up into a hybrid version that suits our needs.

When we understand where technology comes from, we can more effectively engage with its strengths, limitations, and use cases. We can also pick and choose the elements from that technology that we would like to carry into the solutions we build today.

The languages we use were designed and developed in a particular context. Knowing that context gives us multiple powers. One power is the ability to make informed decisions about the languages -- and language features -- we choose in any given situation. Another is the ability to make new languages, new features, and new combinations of features that solve the problem we face today in the way that works best in our current context.

Not knowing context limits us to our own experience. Troy does a wonderful job of demonstrating this using the history of web API practice. I hope my course can help students choose tools and write code more effectively when they encounter new languages and programming styles.

Computing changes. My students don't really know what world they will be working in in five years, or ten, or thirty. Context is a meta-tool that will serve them well.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

February 13, 2022 12:32 PM

A Morning with Billy Collins

It's been a while since I read a non-technical article and made as many notes as I did this morning on this Paris Review interview with Billy Collins. Collins was poet laureate of the U.S. in the early 2000s. I recall reading his collection, Sailing Alone Around the Room, at PLoP in 2002 or 2003. Walking the grounds at Allerton with a poem in your mind changes one's eyes and hears. Had I been blogging by then, I probably would have commented on the experience, and maybe one or two of the poems, in a post.

As I read this interview, I encountered a dozen or so passages that made me think about things I do, things I've thought, and even things I've never thought. Here are a few.

I'd like to get something straightened out at the beginning: I write with a Uni-Ball Onyx Micropoint on nine-by-seven bound notebooks made by a Canadian company called Blueline. After I do a few drafts, I type up the poem on a Macintosh G3 and then send it out the door.

Uni-Ball Micropoint pens are my preferred writing implement as well, though I don't write enough on paper any more to make buying a particular pen much worth the effort. Unfortunately, just yesterday my last Uni-Ball Micro wrote its last line. Will I order more? It's a race between preference and sloth.

I type up most of the things I write these days on a 2015-era MacBook Pro, often connected to a Magic Keyboard. With the advent of the M1 MacBook Pros, I'm tempted to buy a new laptop, but this one serves me so well... I am nothing if not loyal.

The pen is an instrument of discovery rather than just a recording implement. If you write a letter of resignation or something with an agenda, you're simply using a pen to record what you have thought out. In a poem, the pen is more like a flashlight, a Geiger counter, or one of those metal detectors that people walk around beaches with. You're trying to discover something that you don't know exists, maybe something of value.

Programming may be like writing in many ways, but the search for something to say isn't usually one of them. Most of us sit down to write a program to do something, not to discover some unexpected outcome. However, while I may know what my program will do when I get done, I don't always know what that program will look like, or how it will accomplish its task. This state of uncertainty probably accounts for my preference in programming languages over the years. Smalltalk, Ruby, and Racket have always felt more like flashlights or Geiger counters than tape recorders. They help me find the program I need more readily than Java or C or Python.

I love William Matthews's idea--he says that revision is not cleaning up after the party; revision is the party!

Refactoring is not cleaning up after the party; refactoring is the party! Yes.

... nothing precedes a poem but silence, and nothing follows a poem but silence. A poem is an interruption of silence, whereas prose is a continuation of noise.

I don't know why this passage grabbed me. Perhaps it's just the imagery of the phrases "interruption of silence" and "continuation of noise". I won't be surprised if my subconscious connects this to programming somehow, but I ought to be suspicious of the imposition. Our brains love to make connections.

She's this girl in high school who broke my heart, and I'm hoping that she'll read my poems one day and feel bad about what she did.

This is the sort of sentence I'm a sucker for, but it has no real connection to my life. Though high school was a weird and wonderful time for me, as it was for so many, I don't think anything I've ever done since has been motivated in this way. Collins actually goes on to say the same thing about his own work. Readers are people with no vested interest. We have to engage them.

Another example of that is my interest in bridge columns. I don't play bridge. I have no idea how to play bridge, but I always read Alan Truscott's bridge column in the Times. I advise students to do the same unless, of course, they play bridge. You find language like, South won with dummy's ace, cashed the club ace and ruffed a diamond. There's always drama to it: Her thirteen imps failed by a trick. There's obviously lots at stake, but I have no idea what he's talking about. It's pure language. It's a jargon I'm exterior to, and I love reading it because I don't know what the context is, and I'm just enjoying the language and the drama, almost like when you hear two people arguing through a wall, and the wall is thick enough so you can't make out what they're saying, though you can follow the tone.

I feel seen. Back when we took the local daily paper, I always read the bridge column by Charles Goren, which ran on the page with the crossword, crypto cipher, and other puzzles. I've never played bridge; most of what I know about the game comes from reading Matthew Ginsberg's papers about building AI programs to bid and play. Like Collins, I think I was merely enjoying sound of the language, a jargon that sounds serious and silly at the same time.

Yeats summarizes this whole thing in "Adam's Curse" when he writes: "A line will take us hours maybe, / Yet if it does not seem a moment's thought / Our stitching and unstitching has been naught."

I'm not a poet, and my unit of writing is rarely the line, but I know a feeling something like this in writing lecture notes for my students. Most of the worst writing consists of paragraphs and sections I have not spent enough time on. Most of the best sounds natural, a clean distillation of deep understanding. But those paragraphs and sections are the result of years of evolution. That's the time scale on which some of my courses grow, because no course ever gets my full attention in any semester.

When I finish a set of notes, I usually feel like the stitching and unstitching have not yet reached their desired end. Some of the text "seems a moment's thought", but much is still uneven or awkward. Whatever the state of the notes, though, I have move on to the next task: grading a homework assignment, preparing the next class session, or -- worst of all -- performing the administrivia that props up the modern university. More evolution awaits.


This was a good read for a Sunday morning on the exercise bike, well recommended. The line on revision alone was worth the time; I expect it will be a stock tool in my arsenal for years to come.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Software Development, Teaching and Learning

January 13, 2022 2:02 PM

A Quick Follow-Up on What Next

My recent post on what language or tool I should dive into next got some engagement on Twitter, with many helpful suggestions. Thank you all! So I figure I should post a quick update to report what I'm thinking at this point.

In that post, I mentioned JavaScript and Pharo by name, though I was open to other ideas. Many folks pointed out the practical value of JavaScript, especially in a context where many of my students know and use it. Others offered lots of good ideas in the Smalltalk vein, both Pharo and several lighter-weight Squeaks. A couple of folks recommended Glamorous Toolkit (GToolkit), from @feenkcom, which I had not heard of before.

I took to mind several of the suggestions that commenters made about the how to think about making the decision. For example, there is more overhead to studying Pharo and GToolkit than JavaScript or one of the lighter-weight Squeaks. Choosing one of the latter would make it easier to tinker. I think some of these comments had students in mind, but they are true even for my own study during the academic semester. Once I get into a term (my course begins one week from today), my attention gets pulled in many directions for fifteen or sixteen weeks. Being able to quickly switch contexts when jumping into a coding session means that I can jump more often and more productively.

Also, as Glenn Vanderburg pointed out, JavaScript and Pharo aren't likely to teach me much new. I have a lot of background with Smalltalk and, in many ways, JavaScript is just another language. The main benefit of working with either would be practical, not educational.

GToolkit might teach me something, though. As I looked into GToolkit, it became more tempting. The code is Smalltalk, because it is implemented in Pharo. But the project has a more ambitious vision of software that is "moldable": easier to understand, easier to figure out. GToolkit builds on Smalltalk's image in the direction of a computational notebook, which is an idea I've long wanted to explore. (I feel a little guilty that I haven't look more into the work that David Schmüdde has done developing a notebook in Clojure.) GToolkit sounds like a great way for me to open several doors at once and learn something new. To do it justice, though, I need more time and focus to get started.

So I have decided on a two-pronged approach. I will explore JavaScript during the spring semester. This will teach me more about a language and ecosystem that are central to many of my students' lives. There is little overhead to picking it up and playing with it, even during the busiest weeks of the term. I can have a little fun and maybe make some connections to my programming languages course along the way. Then for summer, I will turn my attention to GToolkit, and perhaps a bigger research agenda.

I started playing with JavaScript on Tuesday. Having just read a blog post on scripting to compute letter frequencies in Perl, I implemented some of the same ideas in JavaScript. For the most part, I worked just as my students do: relying on vague memories of syntax and semantics and, when that failed, searching about for examples online.

A couple of hours working like this refreshed my memory on the syntax I knew from before and introduced me to some features that were new to me. It took a few minutes to re-internalize the need for those pesky semicolons at the end of every line... The resulting code is not much more verbose than Perl. I drifted pretty naturally to using functional programming style, as you might imagine, and it felt reasonably comfortable. Pretty soon I was thinking more about the tradeoff between clarity and efficiency in my code than about syntax, which is a good sign. I did run into one of JavaScript's gotchas: I used for...in twice instead of for...of and was surprised by the resulting behavior. Like any programmer, I banged my head on wall for a few minutes and then recovered. But I have to admit that I had fun. I like to program.

I'm not sure what I will write next, or when I will move into the browser and play with interface elements. Suggestions are welcome!

I am pretty sure, though, that I'll start writing unit tests soon. I used SUnit briefly and have a lot of experience with JUnit. Is JSUnit a thing?

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

January 06, 2022 2:47 PM

A Fresh Encounter with Hexapawn

When I was in high school, the sponsor of our our Math Club, Mr. Harpring, liked to give books as prizes and honors for various achievements. One time, he gave me Women in Mathematics, by Lynn Osen. It introduced me to Émilie du Châtelet, Sophie Germain, Emmy Noether, and a number of other accomplished women in the field. I also learned about some cool math ideas.

the initial position of a game of a Hexapawn

Another time, I received The Unexpected Hanging and Other Mathematical Diversions, a collection of Martin Gardner's columns from Scientific American. One of the chapters was about Hexapawn, a simple game played with chess pawns on a 3x3 board. The chapter described an analog computer that learned how to play a perfect game of Hexapawn. I was amazed.

I played a lot of chess in high school and was already interested in computer chess programs. Now I began to wonder what it would be like to write a program that could learn to play chess... I suspect that Gardner's chapter planted one of the seeds that grew into my study of computer science in college. (It took a couple of years, though. From the time I was eight years old, I had wanted to be an architect, and that's where my mind was focused.)

As I wrote those words, it occurred to me that I may have written about the Gardner book before. Indeed I have, in a 2013 post on building the Hexapawn machine. Some experiences stay with you.

They also intersect with the rest of the world. This week, I read Jeff Atwood's recent post about his project to bring the 1973 book BASIC Computer Games into the 21st century. This book contains the source code of BASIC programs for 101 simple games. The earliest editions of this book used a version of BASIC before it included the GOSUB command, so there are no subroutines in any of the programs! Atwood started the project as a way to bring the programs in this book to a new audience, using modern languages and idioms.

You may wonder why he and other programmers would feel so fondly about BASIC Computer Games to reimplement its programs in Java or Ruby. They feel about these books the way I felt about The Unexpected Hanging. Books were the Github of the day, only in analog form. Many people in the 1970s and 1980s got their start in computing by typing these programs, character for character, into their computers.

I was not one of those people. My only access to a computer was in the high school, where I took a BASIC programming class my junior year. I had never seen a book like BASIC Computer Games, so I wrote all my programs from scratch. As mentioned in an old OOPSLA post from 2005, the first program I wrote out of passion was a program to implement a ratings system for our chess club. Elo ratings were great application for a math student and beginning programmer.

Anyway, I went to the project's Github site to check out what was available and maybe play a game or two. And there it was: Hexapawn! Someone has already completed the port to Python, so I grabbed it and played a few games. The text interface is right out of 1973, as promised. But the program learns, also as promised, and eventually plays a perfect game. Playing it brings back memories of playing my matchbox computer from high school. I wonder now if I should write my own program that learns Hexapawn faster, hook it up with the program from the book, and let them duke it out.

Atwood's post brought to mind pleasant memories at a time when pleasant memories are especially welcome. So many experiences create who we are today, yet some seem to have made an outsized contribution. Learning BASIC and reading Martin Gardner's articles are two of those for me.

Reading that blog post and thinking about Hexapawn also reminded me of Mr. Harpring and the effect he had on me as a student of math and as a person. The effects of a teacher in high school or grade school can be subtle and easy to lose track of over time. But they can also be real and deep, and easy not to appreciate fully when we are living them. I wish I could thank Mr. Harpring again for the books he gave me, and for the gift of seeing a teacher love math.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

January 04, 2022 2:54 PM

Which Language Next?

I've never been one to write year-end retrospectives on my blog, or prospective posts about my plans for the new year. That won't change this year, this post notwithstanding.

I will say that 2021 was a weird year for me, as it was for many people. One positive was purchasing a 29" ultra-wide monitor for work at home, seen in this post from my Strange Loop series. Programming at home has been more fun since the purchase, as have been lecture prep, data-focused online meetings, and just about everything. The only downside is that it's in my basement office, which hides me away. When I want to work upstairs to be with family, it's back to the 15" laptop screen. First-world problems.

Looking forward, I'm feeling a little itchy. I'll be teaching programming languages again this spring and plan to inject some new ideas, but the real itch is: I am looking for a new project to work on, and a new language to study. This doesn't have to be a new language, just one that one I haven't gone deep on before. I have considered a few, including Swift, but right now I am thinking of Pharo and JavaScript.

Thinking about mastering JavaScript in 2022 feels like going backward. It's old, as programming languages go, and has been a dominant force in the computing world for well over a decade. But it's also the most common language many of my students know that I have never gone deep on. There is great value in studying languages for their novel ideas and academic interest, but there is also value in having expertise with a language and toolchain that my students already care about. Besides, I've really enjoyed reading about work on JIT compilation of JavaScript over the years, and it's been a long time since I wrote code in a prototype-based OO language. Maybe it's time to build something useful in JavaScript.

Studying Pharo would be going backward for me in a different way. Smalltalk always beckons. Long-time followers of this blog have read many posts about my formative experiences with Smalltalk. But it has been twenty years since I lived in an image every day. Pharo is a modern Smalltalk with a big class library and a goal of being suitable for mission-critical systems. I don't need much of a tug; Smalltalk always beckons.

My current quandary brings to mind a dinner at a Dagstuhl seminar in the summer of 2019 (*). It's been a while now, so I hope my memory doesn't fail me too badly. Mark Guzdial was talking about a Pharo MOOC he had recently completed and how he was thinking of using the language to implement a piece of software for his new research group at Michigan, or perhaps a class he was teaching in the fall. If I recall correctly, he was torn between using Pharo and... JavaScript. He laid out some of the pros and cons of each, with JavaScript winning out on several pragmatic criteria, but his heart was clearly with Pharo. Shriram Krishnamurthi gently encouraged Mark to follow his heart: programming should be joyful, and programming languages allow us to build in languages that give us enjoyment. I seconded the (e)motion.

And here I sit mulling a similar choice.

Maybe I can make this a two-language year.


(*) Argh! I never properly blogged about about this seminar, on the interplay between notional machines and programming language semantics, or the experience of visiting Europe for the first time. I did write one post that mentioned Dagstuhl, Paris, and Montenegro, with an expressed hope to write more. Anything I write now will be filtered through two and a half years of fuzzy memory, but it may be worth the time to get it down in writing before it's too late to remember anything useful. In the meantime: both the seminar and the vacation were wonderful! If you are ever invited to participate in a Dagstuhl seminar, consider accepting.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 31, 2021 12:13 PM

An Experience Rewriting a Piece of Code as as Teaching Tool

Over the last four or five offerings of my compiler course, I have been making progress in how I teach code generation, with teams becoming increasingly successful at producing a working code generator. In the 2019 offering, students asked a few new questions about some low-level mechanical issues in the run-time system. So I whipped up a simple one the night before class, both to refamiliarize myself with the issues and to serve as a potential example. It was not a great piece of software, but it was good enough for a quick in-class demo and as a seed for discussion.

Jump ahead to 2021. As I mentioned in my previous post, this fall's group had a lot more questions about assembly language, the run-time stack, activation records, and the like. When I pulled out my demo run-time system from last time, I found that it didn't help them as much as it had the previous group. The messiness of the code got in the way. Students couldn't see the bigger picture from the explanatory comments, and the code itself seemed opaque to them.

Working with a couple of students in particular, I began to refine the code. First, I commented the higher-level structure of generator more clearly. I then used those comments to reorganize the code bit, with the goal of improving the instructional presentation rather than the code's efficiency or compactness. I chose to leave some comments in rather than to factor out functions, because the students found the linear presentation easier to follow.

Finally, I refined some sections of the code and rewrote others entirely, to make them clearer. At this point, I did extract a helper function or two in an attempty not to obscure the story the program was telling with low-level details.

I worked through two iterations of this process: comment, reorganize, rewrite. At the end, I had a piece of code that is pretty good, and one that is on the student's path to a full code generator.

Of course, I could have designed my software up front and proceeded more carefully as I wrote this code. I mean, professionals and academics understand compiler construction pretty well. The result might well have been a better example of what the run-time generator should look like when students are done.

But I don't think that would have been as helpful to most members of my class. This process was much more like how my students program, and how many of us program, frankly, when we are first learning a new domain. Following this process, and working in direct response to questions students had as we discussed the code, gave me insights into some of the challenges they encounter in my course, including tracking register usage and seeing how the calling and return sequences interact. I teach these ideas in class, but my students were seeing that material as too abstract. They couldn't make the leap to code quite as easily as I had hoped; they were working concretely from the start.

In the end, I ended up with both a piece of code I like and a better handle on how my students approach the compiler project. In terms of outcomes assessment, this experience gives me some concrete ideas for improving the prerequisite courses students take before my course, such as computer organization. More immediately, it helps me improve the instruction in my own course. I have some ideas about how I can reorganize my code generator units and how I might simplify some of my pedagogical material. This may lead to a bigger redesign of the course in a coming semester.

I must admit: I had a lot of fun writing this code -- and revising and improving it! One bit of good news from the experience is that the advice I give in class is pretty good. If they follow my practical suggestions for writing their code, they can be successful. What needs improvement now is finding ways for students to have the relevant bits of advice at hand when they need them. Concrete advice that gets separated from concrete practice tends to get lost in the wind.

Finally, this experience reminded me first hand that the compiler project is indeed a challenge. It's fun, but it's a challenge, especially for undergrads attempting to write their first large piece of software as part of a team. There may be ways I can better help them to succeed.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

December 28, 2021 5:31 PM

Thinking Back on My Compiler Course This Fall

Well, fall semester really got away from me quickly. It seems not long ago that I wrote of launching the course with a renewed mindset of "compilers for the masses, not compilers for compiler people". I'm not sure how well that went this time, as many students came into the course with less understanding of the underlying machine model and assembly language than ever before. As a result, many of them ended up stressing over low-level implementation details while shoring up that knowledge than thinking about some of the higher-level software engineering ideas. I spent more time this semester working with more teams to help them understand parsing rules, semantic actions, and activation records than in anytime I can remember.

I suspect that the students' programming maturity and state of knowledge at the start of the course are in large part a result of experiencing the previous two and a half semesters under the damper of the pandemic. Some classes were online, others were hybrid, and all were affected by mitigation efforts, doubt, and stress. Students and professors alike faced these effects, me included, and while everyone has been doing the best they could under the circumstances, sometimes the best we can do comes up a little short.

At the beginning of the course, I wrote about a particular uncertainty raised by the preceding pandemic semesters: how isolation and the interruption of regular life had reduced the chances for students to make friends in the major and to build up personal and professional connections with their classmates. I underestimated, I think, the effect that the previous year and a half would have on learning outcomes in our courses.

The effect on project teams themselves turned out to be a mixed bag. Three of the five teams worked pretty well together, even if one of the teammates was unable to contribute equally to the project. That's pretty typical. Two other teams encountered more serious difficulties working together effectively. Difficulties derailed one project that got off to an outstanding start, and the second ended up being a one-person show (a very impressive one-person show, in fact). In retrospect, many of these challenges can be traced back to problems some students had with content: they found themselves falling farther behind their teammates and responded by withdrawing from group work. The result is a bad experience for those still plugging along.

That's perhaps too many words about the difficulties. Several teams seemed to have pretty typical experiences working one another, even though they didn't really know each other before working together.

The combination of some students struggling with course content and some struggling with collaboration led to mixed bag of results. Two teams produced working compilers that handled essentially all language features correctly, or nearly so. That's pretty typical for a five-team semester. One team produced an incomplete system, but one they could be proud of after working pretty hard the entire semester. That's typical, too.

Two teams produced systems without code generators beyond a rudimentary run-time system. That's a bit unusual. These teams were disappointed because they had set much higher goals for themselves. Many of these students were taking heavy course and research loads and, unfortunately, all that work eventually overwhelmed them. I think I felt as bad for them as they did, knowing what they might have accomplished with a more forgiving schedule. I do hope they found some value in the course and will be able to look back on the experience as worthwhile. They learned a lot about working on a big project, and perhaps about themselves.

What about me? A few weeks into the course, I declared that I was programming like a student again, trying to implement the full compiler project I set before my students. Like many of my students, I accomplished some of my goals and fell short when outside obstacles got in the way. One the front end, my scanner is in great shape, while my parser is correct but in need of some refactoring. At that point in the semester, I got busy both with department duties and with working one on one with the teams, and my productivity dropped off.

I did implement a solid run-time system, one I am rather happy with. My work on it came directly out of answering students' questions about code generation and working with them to investigate and debug their programs. I'll have more to say about my run-time system in the next post.

So, my latest compiler course is in the books. All in all, my students and I did about as well as we could under the circumstances. There is still great magic in watching a team's compiler generate an executable, then running that executable on an input that produces tens of thousands of activation records and executes several million lines of assembly. The best we can do is often quite good enough.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

November 28, 2021 10:35 AM

Students Need to Develop Microskills, Too

Yesterday someone retweeted this message from Hillel Wayne into my timeline:

A surprising and undervalued aspect of mastery comes from narrow-scope "microskills". In software, these would be things like

- Python list comprehensions
- Grep flags
- Debugging specific error messages
- Using a window manager

We can, and should, do targeted training.

Later in the short thread, Hillel says something that brought my students to mind:

In other words, the high level thinking is the difference between a task being possible and impossible, but the microskills are the difference between a task being 20 minutes and six hours. That's why it can take us days to find the right one-liner.

Some students love to program and look for every opportunity to write code. These students develop a satchelful of microskills, usually far behind what we could every teach them or expose them to in class. They tend to do fine on the programming assignments we give in class.

Other students complain that a programming assignment I gave them, intended as a one-hour practice session, took them eight or ten hours. My first reaction is usually to encourage them never to spin their wheels that long without asking me a question. I want them to develop grit, but usually that kind of wheel spinning is a sign that they may be missing a key idea or piece of information. I'd like to help them get moving sooner.

There is another reason, though, that many of these students spin their wheels. For a variety of reasons, they program only when they are required by a class. They are ambivalent about programming, either because they don't find it as interesting as their peers or because they don't enjoy the grind of working in the trenches yet. I say "yet" because one of the ways we all come to enjoy the grind is... to grind away! That's how we develop the microskills Hillel is talking about, which turn a six-hour task into a 20-minute task, or a disappointing one-hour experience with a homework problem into a five-minute joy.

Students who have yet to experience the power of microskills are prone to underestimate their value. That makes it less enjoyable to practice programming, which makes it hard to develop new skills. It's a self-reinforcing loop, and not the kind we want to encourage in our students.

Even after all these years in the classroom, I still struggle to find ways to help my students practice programming skills in a steady, reliable way. Designing engaging problems to work on helps. So does letting students choose the problems they work on, which works better in some courses than others. Ultimately, though, I think what works best is to develop as much of a personal relationship with each student as possible. This creates a condition in which they are more inclined to ask for help when they need it and to trust suggestions from that sound a little crazy to the beginner's mind.

I am teaching my compiler development course this semester, which means that I am working with students near the end of their time with us, whose habits are deeply ingrained from previous courses. The ones who don't already possess a few of the microskills they need are struggling as the task of writing a parser or semantic checker or code generator stretches out like an endless desert before them.

Next semester, I teach my programming languages course and have the joy of introducing my students to Racket and functional programming. This essay me already thinking of how I can help my students develop some of the microskills they will want and need in the course and beyond. Perhaps a more explicit focus early on the use Dr. Racket to create, run, test, and debug code can set them up for a more enjoyable experience later in the course -- and help put them on a virtuous self-reinforcing loop developing skills and using them to enjoy the next bit of learning they do.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

October 28, 2021 3:52 PM

A Few Quotes from "The Triggering Town"

A couple of weeks back, I saw an article in which Malcom Gladwell noted that he did not know The Triggering Town, a slim book of essays by poet Richard Hugo. I was fortunate to hear about Hugo many years ago from software guru Richard Gabriel, who is also a working poet. It had been fifteen years or more since I'd read The Triggering Town, so I stopped into the library on my way home one day and picked it up. I enjoyed it the second time around as much as the first.

I frequently make notes of passages to save. Here are five from this reading.

Actually, the hard work you do on one poem is put in on all poems. The hard work on the first poem is responsible for the sudden ease of the second. If you just sit around waiting for the easy ones, nothing will come. Get to work.

That advice works for budding software developers, too.

Emotional honesty is a rare thing in the academic world or anywhere else for that matter, and nothing is more prized by good students.

Emotion plays a much smaller role in programming than in writing poetry. Teaching, though, is deeply personal, even in a technical discipline. All students value emotional honesty, and profs who struggle to be open usually struggle making connections to their students.

Side note: Teachers, like policemen, firemen, and service personnel, should be able to retire after twenty years with full pension. Our risks may be different, but they are real. In twenty years most teachers have given their best.

This is a teacher speaking, so take the recommendation with caution. But more than twenty years into this game, I know exactly what Hugo means.

Whatever, by now, I was old enough to know explanations are usually wrong. We never quite understand and we can't quite explain.

Yet we keep trying. Humans are an optimistic animal, which is one of the reasons we find them so endearing.

... at least for me, what does turn me on lies in a region of myself that could not be changed by the nature of my employment. But it seems important (to me even gratifying) that the same region lies untouched and unchanged in a lot of people, and in my innocent way I wonder if it is reason for hope. Hope for what? I don't know. Maybe hope that humanity will always survive civilization.

This paragraph comes on the last page of the book and expresses one of the core tenets of Hugo's view of poetry and poets. He fought in World War 2 as a young man, then worked in a Boeing factory for 15-20 years, and then became an English professor at a university. No matter the day job, he was always a poet. I have never been a poet, but I know quite well the region of which he speaks.

Also: I love the sentence, "Maybe hope that humanity will always survive civilization."

Posted by Eugene Wallingford | Permalink | Categories: Personal, Software Development, Teaching and Learning

September 27, 2021 2:04 PM

Programming Like a Student Again

For the first time in many years, I got the urge this fall to implement the compiler project I set before my students.

I've written here about this course many times over the years. It serves students interested in programming languages and compilers as well as students looking for a big project course and students looking for a major elective. Students implement a compiler for a small language by hand in teams of 2-5, depending on the source language and the particular group of people in the course.

Having written small compilers like this many times, I don't always implement the entire project each offering. That would not be a wise use of my time most semesters. Instead, when something comes up in class, I will whip up a quick scanner or type checker or whatever so that we can explore an idea. In recent years, the bits I've written have tended to be on the backend, where I have more room to learn.

But this fall, I felt the tug to go all in.

I created a new source language for the class this summer, which I call Twine. Much of its concrete syntax was inspired by SISAL, a general-purpose, single-assignment functional language with implicit parallelism and efficient array handling. SISAL was designed in the mid-1980s to be a high-level language for large numerical programs, to be run on a variety of multiprocessors. With advances in multiprocessors and parallel processors, SISAL is well suited for modern computation. Of course, it contains many features beyond what we can implement in a one-semester compiler course where students implement all of their own machinery. Twine is essentially a subset of SISAL, with a few additions and modifications aimed at making the language more suitable for our undergraduate course.

the logo of the Twine programming language

(Whence the name "Twine"? The name of SISAL comes from the standard Unix word list. It was chosen because it contains the phrase "sal", which is an acronym for "single assignment language". The word "sisal" itself is the name of a flowering plant native to southern Mexico but widely cultivated around the world. Its leaves are crushed to extract a fiber that is used to create rope and twine. So, just as the sisal plant is used to create twine, the SISAL programming language was used to create the Twine programming language.)

With new surface elements, the idea of implementing a new front end appealed to me. Besides, the experience of implementing a complete system feels different than implementing a one-off component... That's one of the things we want our students to experience in our project courses! After eighteen months of weirdness and upheaval at school and in the world, I craved that sort of connection to some code. So here I am.

Knocking out a scanner in my free time over the last week and getting started on my parser has been fun. It has also reminded me how the choice of programming language affects how I think about the code I am writing.

I decided to implement in Python, the language most of my student teams are using this fall, so that I might have recent experience with specific issues they encounter. I'd forgotten just how list-y Python is. Whenever I look at Python code on the web, it seems that everything is a list or a dictionary. The path of least resistance flows that way... If I walk that path, I soon find myself with a list of lists of lists, and my brain is swimming in indices. Using dictionaries replaces integer indices with keys of other types, but the conceptual jumble remains.

It did not take me long to appreciate anew why I like to work with objects. They give me the linguistic layers I need to think about my code independent of languages primitives. I know, I know, I can achieve the same thing with algebraic types and layers of function definitions. However, my mind seems to work on a wavelength where data encapsulation and abstract messages go together. Blame Smalltalk for ruining me, or enlightening me, whichever your stance.

Python provides a little extra friction to classes and objects that seems to interrupt my flow occasionally. For a few minutes this week, I felt myself missing Java and wondering if I ought to have chosen it for the project instead of Python. I used to program in Java every day, and this was the first time in a long while that I felt the pull back. After programming so much in Racket the last decade, though, the wordiness of Java keeps me away. Alas, Python is not the answer. Maybe I'm ready to go deep on a new language, but which one? OOP doesn't seem to be in vogue these days. Maybe I need to return to Ruby or Smalltalk.

For now I will live with OOP in Python and see whether its other charms can compensate. Living with Python's constraints shows up as a feature of another choice I made for this project: to let pycodestyle tell me how to format my code. This is an obstacle for any programmer who is as idiosyncratic as I am. After a few rounds of reformatting my code, though, I am finding surrender easier to accept. This has freed me to pay attention to more important matters, which is one of the keys ideas behind coding and style standards in the first place. But I am a slow learner.

It's been fun so far. I look forward to running Twine programs translated by my compiler in a few weeks! As long as I've been programming, I have never gotten over the thrill of watching my compiler I've written -- or any big program I've written -- do its thing. Great joy.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

August 29, 2021 10:19 AM

Launching the Compiler Project with New Uncertainties

We will be forming project teams in my course this week, and students will begin work in earnest on Friday. Or so thinks the prof, who releases the first assignment on Thursday... I can dream.

I noticed one change this year when I surveyed students about their preferences for forming teams. In an ordinary year, most students submit at least one or two names of others in the class with whom they'd like to work; some already have formed the teams they want to work in. A few indicate someone they'd rather not work with, usually based on experiences in previous courses. This helps me help them form teams with a mix of new and familiar, with some hedge against expected difficulties. It's never perfect, but most years we end up with a decent set of teams and project experiences.

This year, though, students barely offered any suggestions for forming teams. Most students expressed no preference for whom they want to work with, and no one indicated someone they don't want to work with.

At first, this seemed strange to me, but then I realized that it is likely an effect of three semesters distorted by COVID-19. With one semester forced online and into isolation, a second semester with universal masking, no extracurricular activities, and no social life, and a third semester with continued masking and continued encouragement not to gather, these students have had almost no opportunitiy to get to know one another!

This isolation eliminates one of the great advantages of a residential university, both personally and professionally. I made so many friends in college, some of whom I'm still close to, and spent time with them whenever I wasn't studying (which, admittedly, was a lot). But it also affects the classroom, where students build bonds over semesters of taking courses together in various configurations. Those bonds carry over into a project course such as mine, where they lubricate the wheels of teams who have to work together more closely than before. They at least begin the project knowing each other a bit and sharing a few academic experiences.

Several students in my class this semester said, "I have no friends in this class" or even "I don't know any other CS majors". That is sad. It also raises the stakes for the compiler project, which may be there only chance to make acquaintances in their major before they graduate. I feel a lot more responsibility as I begin to group students into teams this semester, even as I know that I have less information available than ever before for doing a credible job.

I'm going to keep all this in mind as the semester unfolds and pay closer attention to how students and teams seem to be doing. Perhaps this course can not only help them have a satisfying and educational experience building a big piece of software, but also help them form some of the personal bonds that add grace notes to their undergrad years.


On an unrelated note, I received word a couple of weeks ago that this blog had been selected by Feedspot as one of the Top 20 Computer Science Blogs on the web. It's always nice to be recognized in this way. Given how little little I've blogged over the last couple of years, it is rather generous to include me on this list! I see there a number of top-quality blogs, several of which I read religiously, and most of which post entries with admirable regularity. It remains a goal of mine to return to writing here more regularly. Perhaps two entries within a week, light as they are, offer hope.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

August 27, 2021 3:30 PM

Back To My Compilers Course

Well, a month has passed. Already, the first week of classes are in the books. My compiler course is off to as good a start as one might hope.

Week 1 of the course is an orientation to the course content and project. Content-wise, Day 1 offers a bird's-eye view of what a compiler does, then Day 2 tries to give a bird's-eye view of how a compiler works. Beginning next week, we go deep on the stages of a compiler, looking at techniques students can use to implement their compiler for a small language. That compiler project is the centerpiece and focus of the course.

Every year, I think about ways to shake up this course. (Well, not last year, because we weren't able to offer it due to COVID.) As I prepared for the course, I revisited this summary of responses to a Twitter request from John Regehr: What should be taught in a modern undergrad compiler class? It was a lot of fun to look back through the many recommendations and papers linked there. In the end, though, the response that stuck with me came from Celeste Hollenbeck, who "noted the appeal of focusing on the basics over esoterica": compilers for the masses, not compilers for compiler people.

Our class is compilers for everyone in our major, or potentially so. Its main role in our curriculum is to be one of four so-called project courses, which serve as capstones for a broad set of electives. Many of the students in the course take it to satisfy their project requirement, others take it to satisfy a distribution requirement, and a few take it just because it sounds like fun.

The course is basic, and a little old-fashioned, but that works for us. The vast majority of our students will never write a compiler again. They are in the course to learn something about how compilers work conceptually and to learn what it is like to build a large piece of software with a team. We talk about modern compiler technology such as LLVM, but working with such complicated systems would detract from the more general goals of the course for our students. Some specific skills for writing lexers and scanners, a little insight into how compilers work, and experience writing a big program with others (and living with design decisions for a couple of months!) are solid outcomes for an undergrad capstone project.

That's not to say that some students don't go on to do more with compilers... Some do. A few years ago, one of our undergrads interviewed his way into an internship with Sony PlayStation's compiler team, where he now works full time. Other students have written compilers for their own languages, including one that was integrated as a scripting language into a gaming engine he had built. In that sense, the course seems to serve the more focused students well, too.

Once more unto the breach, dear friends, once more...
-- Henry V

So, we are off. I still haven't described the source language my students will be processing this semester, as promised in my last post. Soon. Since then, though, I wrote a bunch of small programs in the language just to get a feel for it. That's as much fun as a department head gets to have most days these days.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

May 19, 2021 3:07 PM

Today's Thinking Prompts, in Tweets

On teaching, via Robert Talbert:

Look at the course you teach most often. If you had the power to remove one significant topic from that course, what would it be, and why?

I have a high degree of autonomy in most of the courses I teach, so power isn't the limiting factor for me. Time is a challenge to making big changes, of course. Gumption is probably what I need most right now. Summer is a great time for me to think about this, both for my compiler course this fall and programming languages next spring.

On research, via Kris Micinski:

i remember back to Dana Scott's lecture on the history of the lambda calculus where he says, "If Turing were alive today, I don't know what he'd be doing, but it wouldn't be recursive function theory." I think about that a lot.

Now I am, too. Seriously. I'm no Turing, but I have a few years left and some energy to put into something that matters. Doing so will require some gumption to make other changes in my work life first. I am reaching a tipping point.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

May 06, 2021 3:19 PM

Sometimes You Have To Just Start Talking

I have been enjoying a few of James Propp's essays recently. Last month he wrote about the creation of zero. In Who Needs Zero, he writes:

But in mathematics, premature attempts to reach philosophical clarity can get in the way of progress both at the individual level and at the cultural level. Sometimes you have to just start talking before you understand what you're talking about.

This reminded me of a passage by Iris Murdoch in Metaphysics as a Guide to Morals, which I encountered in one of Robin Sloan's newsletters:

The achievement of coherence is itself ambiguous. Coherence is not necessarily good, and one must question its cost. Better sometimes to remain confused.

My brain seems hardwired to seek out and create abstractions. Perhaps it's just a deeply ingrained habit. Even so I am a pragmatist at heart. As Propp says, "Zero is as zero does."

Allowing oneself to remain confused, to forge ahead without having reached clarity yet, is essential to doing research, or to learning anything at all, really.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

April 30, 2021 1:56 PM

Good News at the End of a Long Year, v2.0

A couple of weeks ago, a former student emailed me after many years. Felix immigrated to the US from the Sudan back in the 1990s and wound up at my university, where he studied computer science. While in our program, he took a course or two with me, and I supervised his undergrad research project. He graduated and got busy with life, and we lost touch.

He emailed to let me know that he was about to defend his Ph.D. dissertation, titled "Efficient Reconstruction and Proofreading of Neural Circuits", at Harvard. After graduating from UNI, he programmed at DreamWorks Interactive and EA Sports, before going to grad school and working to "unpack neuroscience datasets that are almost too massive to wrap one's mind around". He defended his dissertation successfully this week.

Congratulations, Dr. Gonda!

Felix wrote initially to ask permission to acknowledge me in his dissertation and defense. As I told him, it is an honor to be remembered so fondly after so many years. People often talk about how teachers affect their students' futures in ways that are often hard to see. This is one of those moments for me. Arriving at the end of what has been a challenging semester in the classroom for me, Felix's note boosted my spirit and energizes me a bit going into the summer.

If you'd like to learn more about Felix and his research, here is his personal webpage The Harvard School of Engineering also has a neat profile of Felix that shows you what a neat person he is.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

April 23, 2021 3:59 PM

A Positive Story at the End of a Long Year

This is short story about a student finding something helpful in class and making my day, preceded by a long-ish back story.

In my programming languages course yesterday, I did a session on optimization. It's a topic of some importance, and students are usually interested in what it means for an interpreter or compiler to "optimize" code. I like to show students a concrete example that demonstrates the value of an optimization. Given where we are in the course and the curriculum, though, it would be difficult to do that with a full-featured language such as Python or Java, or even Racket. On the other end of the spectrum, the little languages they have been implementing and using all semester are too simple to benefit from meaningful optimization.

I found a sweet spot in between these extremes with BF. (Language alert!) I suppose it is more accurate to say that Eli Bendersky found the sweet spot, and I found Bendersky's work. Back in 2017, he wrote a series of blog posts on how to write just-in-time compilers, using BF as his playground. The first article in that series inspired me to implement something similar in Python and to adapt it for use with my students.

BF is well-suited for my purposes. It is very simple language, consisting of only eight low-level operators. It is possible to write a small interpreter for BF that students with only a background in data structures can understand. Even so, the language is Turing complete, which means that we can write interesting and arbitrarily complex programs.

The low-level simplicity of BF combines with its Turing completeness to create programs that are horribly inefficient if they are interpreted in a naive manner. There are many simple ways to optimize BF programs, including creating a jump table to speed up loops and parsing runs of identical opcodes (moves, increments, and decrements) as more efficient higher-level operators. Even better, the code to implement these optimizations is also understandable to a student with only data structures and a little background in programming languages.

My session is built around a pair of interpreters, one written in a naive fashion and the other implementing an optimization. This semester, we preprocessed BF programs to compute a table that makes jumping to the beginning or end of a loop an O(1) operation just like BF's other six primitives. The speed-up on big BF programs, such as factoring large numbers or computing a Mandelbrot set, is impressive.

Now to the story.

At the end of class, I talk a bit about esoteric languages more broadly as a way for programmers to test the boundaries of programming language design, or simply to have fun. I get to tell students a story about a four-hour flight back from OOPSLA one year during which I decided to roll a quick interpreter for Ook in Scheme. (What can I say; programming is fun.)

To illustrate some of the fun and show that programmers can be artists, too, I demo programs in the language Piet, which is named for the Dutch abstract painter Piet Mondrian. He created paintings that look like this:

a Piet program that prints 'Piet'

That is not a Mondrian, but it is a legal program in the Piet language. It prints 'Piet'. Here is another legal Piet program:

a Piet program that prints 'Hello, World'

It prints "Hello, World". Here's another:

a Piet program that determines if a number is prime

That program reads an integer from standard input, determines whether it is prime or not, and prints 'Y' or 'N'. Finally, how about this:

a Piet program that prints 'tetris'

If you are a certain age, you may notice something special about this image: It is made up exclusively of Tetris pieces. The program prints... "Tetris". Programming truly is an art!

One of my students was inspired. While reviewing the session notes, he searched for more information about Piet online and found this interactive editor. He then used it to create a Piet program in honor of a friend of his who passed away earlier this semester. It prints the Xbox gamertag of his late friend. In his email to me, he said that writing this program was therapeutic.

I'm not sure one of my class sessions has ever had a more important outcome. I'm also not sure that I have ever been happier to receive email from a student.

This has been a tough year for most everyone, and especially for students who are struggling with isolation and countermeasures against a nasty virus. I'm so glad that programming gave one student a little solace, at least for an evening. I'm also glad he shared his story with me.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

March 25, 2021 4:18 PM

Teaching Yourself the Material

A common complaint from students is that the professor makes them teach themselves then material.

From In Defense of Teaching Yourself the Material:

Higher education institutions must orient themselves toward teaching students how to teach themselves, or risk becoming irrelevant. I'll add to the above that self-teaching (and self-regulation) are also valuable job skills. During my time at Steelcase, I learned that what the company wanted was not so much a recent college graduate with straight A's, but someone who could learn quickly and get up to speed without having to pull someone else off their job to teach them. So self-teaching is not only the ultimate goal of higher education and the main instantiation of lifelong learning, it's also what gives graduates a competitive advantage on the job market and sets them up not to be stuck in a loop for their careers. I want my students to be able to say truthfully in an interview, when asked why they should be hired: I know how to learn things, and learn fast, without a lot of hand-holding. That is music to the employer's ears. The word will get out about which colleges equip students well in this area. Similarly for those that don't.

Talbert has more to say about the value of students' being able to teach themselves. One of our jobs as instructors is to provide the scaffolding that students need to learn how to do this effectively in our discipline, and then slowing dismantle the scaffold and let students take over.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

February 28, 2021 9:47 AM

Find Your Passion? Master Something.

A few weeks ago, a Scott Galloway video clip made the rounds. In it, Galloway was saying something about "finding your passion" that many people have been saying for a long time, only in that style that makes Galloway so entertaining. Here's a great bit of practical advice on the same topic from tech guru Kevin Kelly:

Following your bliss is a recipe for paralysis if you don't know what you are passionate about. A better motto for most youth is "master something, anything". Through mastery of one thing, you can drift towards extensions of that mastery that bring you more joy, and eventually discover where your bliss is.

My first joking thought when I read this was, "Well, maybe not anything..." I mean, I can think of lots of things that don't seem worth mastering, like playing video games. But then I read about professional gamers making hundreds of thousands of dollars a year, so who am I to say? Find something you are good at, and get really good at it. As Galloway says, like Chris Rock before him, it's best to become good at something that other people will pay you for. But mastery of anything opens doors that passion can only bang on.

The key to the "master something, anything" mantra is the next sentence of Kelly's advice. When we master something, our expertise creates opportunities. We can move up or down the hierarchy of activities built from that mastery, or to related domains. That is where we are most likely to find the life that brings us joy. Even better, we will find it in a place where our mastery helps us get through the inevitable drudge work and over the inevitable obstacles that will pop in our way. I love to program, but some days debugging is a slog, and other days I butt up against thorny problems beyond my control. The good news is that I have skills to get through those days, and I like what I'm doing enough to push on through to the more frequent moments and days of bliss.

Passion is wonderful if you have it, but it's hard to conjure up on its own. Mastering a skill, or a set of skills, is something every one of us can do, and by doing it we can find our way to something that makes us happy.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

January 08, 2021 2:12 PM

My Experience Storing an Entire Course Directory in Git

Last summer, I tried something new: I stored the entire directory of materials for my database course in Git. This included all of my code, the course website, and everything else. It worked well.

The idea came from a post or tweet many years ago by Martin Fowler who, if I recall correctly, had put his entire home directory under version control. It sounded like the potential advantages might be worth the cost, so I made a note to try it myself sometime. I wasn't quite ready last summer to go all the way, so I took a baby step by creating my new course directory as a git repo and growing it file by file.

My context is pretty simple. I do almost all of my work on a personal MacBook Pro or a university iMac in my office. My main challenge is to keep my files in sync. When I make changes to a small number of files, or when the stakes of a missing file are low, copying files by hand works fine, with low overhead and no tooling necessary.

When I make a lot of changes in a short period of time, however, as I sometimes do when writing code or building my website, doing things by hand becomes more work. And the stakes of losing code or web pages are a lot higher than losing track of some planning notes or code I've been noodling with. To solve this problem, for many years I have been using rsync and a couple of simple shell scripts to manage code directories and my course web sites.

So, the primary goal for using Git in a new workflow was to replace rsync. Not being a Git guru, as many of you are, I figured that this would also force me to live with git more often and perhaps expand my tool set of handy commands.

My workflow for the semester was quite simple. When I worked in the office, there were four steps:

  1. git merge laptop
  2. [ do some work ]
  3. git commit
  4. git push

On my laptop, the opening and closing git commands changed:

  1. git pull origin main
  2. [ do some work ]
  3. git commit
  4. git push origin laptop

My work on a course is usually pretty straightforward. The most common task is to create files and record information with commit. Every once in a while, I had to back up a step with checkout.

You may say, "But you are not using git for version control!" You would be correct. The few times I checked out an older version of a file, it was usually to eliminate a spurious conflict, say, a .DS_Store file that was out of sync. Locally, I don't need a lot of version control, but using Git this way was a form of distributed version control, making sure that, wherever I was working, I had the latest version of every file.

I think this is a perfectly valid way to use Git. In some ways, Git is the new Unix. It provided me with a distributed filesystem and a file backup system all in one. The git commands ran effectively as fast as their Unix counterparts. My repo was not very much bigger than the directory would have been on its own, and I always had a personal copy of the entire repo with me wherever I went, even if I had to use another computer.

Before I started, several people reminded me that Git doesn't always work well with large images and binaries. That didn't turn out to be much of a problem for me. I had a couple of each in the repo, but they were not large and never changed. I never noticed a performance hit.

The most annoying hiccup all semester was working with OS X's .DS_Store files, which record screen layout information for OS X. I like to keep my windows looking neat and occasionally reorganize a directory layout to reflect what I'm doing. Unfortunately, OS X seems to update these files at odd times, after I've closed a window and pushed changes. Suddenly the two repos would be out of sync only because one or more .DS_Store files had changed after the fact. The momentary obstacle was quickly eliminated with a checkout or two before merging. Perhaps I should have left the .DS_Stores untracked...

All in all, I was pretty happy with the experience. I used more git, more often, than ever before and thus am now a bit more fluent than I was. (I still avoid the hairier corners of the tool, as all right-thinking people do whenever possible.) Even more, the repository contains a complete record of my work for the semester, false starts included, with occasional ruminations about troubles with code or lecture notes in my commit messages. I had a little fun after the semester ended looking back over some of those messages and making note of particular pain points.

The experiment went well enough that I plan to track my spring course in Git, too. This will be a bigger test. I've been teaching programming languages for many years and have a large directory of files, both current and archival. Not only are there more files, there are several binaries and a few larger images. I'm trying decide if I should put the entire folder into git all at once upfront or start with an empty folder a lá last semester and add files as I want or need them. The latter would be more work at early stages of development but might be a good way to clear out the clutter that has built up over twenty years.

If you have any advice on that choice, or any other, please let me know by email or on Twitter. You all have taught me a lot over the years. I appreciate it.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

December 31, 2020 12:33 PM

Go Home and Study

In a conversation with Tyler Cowen, economist Garett Jones said:

... my job in the classroom is not to teach the details of any theory. My job is to give students a reason to feel passionate enough about the topic so that they'll go home for two or three hours and study it on their own.

Perhaps this is a matter of context, but I don't think this assetion is entirely accurate. It might give the wrong impression to the uninitiated by leaving an essential complementary task implicit.

One could read this as saying that the instructor's job is purely one of motivation. Closures! Rah-rah! Get students excited enough to go learn everything about them on the own, and the instructor has succeeded.

If you think that's true, then I can introduce you to many students who have struggled or failed to learn something new despite being excited to learn and putting in a lot of time. They were missing some prerequisite knowledge or didn't have the experience they needed to navigate the complexities of a new area of study. In principle, if they plugged away at it long enough, they would eventually get there, but then why bother having an instructor at all?

So I think that, as instructor, I have two jobs. I do need to motivate students to put in the time and effort they need to study. Learning happens inside the student, and that requires personal study. I also, though, have to help create the conditions under which they can succeed. This involves all sorts of things: giving them essential background, pointing them toward useful resources, helping them practice the skills they'll need to learn effectively, and so on.

Motivation is in some ways a necessary part of the instructor's job. If students don't want to invest time in study and practice, then they will not learn much. But motivation is not sufficient. The instructor must also put the student in position to succeed to learn effectively.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

December 30, 2020 3:38 PM

That's a Shame

In the middle of an old post about computing an "impossible" integral, John Cook says:

In the artificial world of the calculus classroom, everything works out nicely. And this is a shame.

When I was a student, I probably took comfort in the fact that everything was supposed to work out nicely on the homework we did. There *was* a solution; I just had to find the pattern, or the key that turned the lock. I suspect that I was a good student largely because I was good at finding the patterns, the keys.

It wasn't until I got to grad school that things really changed, and even then course work was typically organized pretty neatly. Research in the lab was very different, of course, and that's where my old skills no longer served me so well.

In university programs in computer science, where many people first learn how to develop software, things tend to work out nicely. That is a shame, too. But it's a tough problem to solve.

In most courses, in particular introductory courses, we create assignments with that have "closed form" solutions, because we want students to practice a specific skill or learn a particular concept. Having a fixed target can be useful in achieving the desired outcomes, especially if we want to help students build confidence in their abilities.

It's important, though, that we eventually take off the training wheels and expose students to messier problems. That's where they have an opportunity to build other important skills they need for solving problems outside the classroom, which aren't designed by a benevolent instructor to have follow a pattern. As Cook says, neat problems can create a false impression that every problem has a simple solution.

Students who go on to use calculus for anything more than artificial homework problems may incorrectly assume they've done something wrong when they encounter an integral in the wild.

CS students need experience writing programs that solve messy problems. In more advanced courses, my colleagues and I all try to extend students' ability to solve less neatly-designed problems, with mixed results.

It's possible to design a coherent curriculum that exposes students to an increasingly messy set of problems, but I don't think many universities do this. One big problem is that doing so requires coordination across many courses, each of which has its own specific content outcomes. There's never enough time, it seems, to teach everything about, say, AI or databases, in the fifteen weeks available. It's easier to be sure that we cover another concept than it is to be sure students take a reliable step along the path from being able to solve elementary problems to being able to solve to the problems they'll find in the wild.

I face this set of competing forces every semester and do my best to strike a balance. It's never easy.

Courses that involve large systems projects are one place where students in my program have a chance to work on a real problem: writing a compiler, an embedded real-time system, or an AI-based system. These courses have closed form solutions of sorts, but the scale and complexity of the problems require students to do more than just apply formulas or find simple patterns.

Many students thrive in these settings. "Finally," they say, "this is a problem worth working on." These students will be fine when they graduate. Other students struggle when they have to do battle for the first time with an unruly language grammar or a set of fussy physical sensors. One of my challenges in my project course is to help this group of students move further along the path from "student doing homework" to "professional solving problems".

That would be a lot easier to do if we more reliably helped students take small steps along that path in their preceding courses. But that, as I've said, is difficult.

This post describes a problem in curriculum design without offering any solutions. I will think more about how I try to balance the forces between neat and messy in my courses, and then share some concrete ideas. If you have any approaches that have worked for you, or suggestions based on your experiences as a student, please email me or send me a message on Twitter. I'd love to learn how to do this better.

I've written a number of posts over the years that circle around this problem in curriculum and instruction. Here are three:

I'm re-reading these to see if past me has any ideas for present-day me. Perhaps you will find them interesting, too.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 28, 2020 9:23 AM

Fall Semester Hit Me Harder Than I Realized

(This is an almost entirely personal entry. If that's not your thing, feel free to move on.)

Last Monday morning, I sat down and wrote a blog entry. It was no big deal, just an observation from some reading I've been doing. A personal note, a throwaway. I'm doing the same this morning.

I'd forgotten how good that can feel, which tells you something about my summer and fall.

Last spring, I wrote that I would be teaching a new course in the fall. I was pretty excited for the change of pace, even if it meant not teaching my compiler course this year, and was already thinking ahead to course content, possible modes of delivery in the face of Covid-19, and textbooks.

Then came summer.

Some of my usual department head tasks, like handling orientation sessions for incoming first-year students, were on the calendar, but the need to conduct them remotely expanded what used to be a few hours of work each week to a few hours each day. (It must have been even worse for the university staff who organize and run orientation!) Uncertainty due to the pandemic and the indecisiveness of upper administration created new work, such as a seemingly endless discussion of fall schedule, class sizes, and room re-allocation.

One of the effects of all this work was that, when August rolled around, I was not much better prepared to teach my class than I had been in May when I solicited everyone's advice.

Once fall semester started, my common refrain in conversations with friends was, "It feels like I'm on a treadmill." As soon as I finished preparing a week's in-class session, I had to prepare the week's online activity. Then there were homework assignments to write, and grade. Or I had to write an exam, or meet with student's to discuss questions or difficulties, made all the more difficult but the stress the pandemic placed on them. I never felt like I could take a day or hour off, and when I did, class was still there in my mind, reminding of all I had to do before another week began and the cycle began again.

That went on for fourteen weeks. I didn't feel out of sorts so much as simply always busy. It would be over soon enough, my rational mind told me.

When the semester ended at Thanksgiving, the treadmill of new work disappeared and all that was left was the grading. I did not rush that work, letting it spread over most of the week and a half I had before grades were due. I figured that it was time to decompress a bit.

After grades were in and I had time to get back to normal, I noticed some odd things happening. First of all I was sleeping a lot: generous naps most days, and a couple of Fridays where I was in bed for ten hours of rest (followed, predictably, by a nap later in the day). I'm no insomniac by nature, but this was much more sleep than I usually take, or need.

My workout data told a tale of change, too. My elliptical and bike performances had been steadily showing the small improvements of increased capability through May or so. They leveled off into the summer months, when I was able to ride outside more with my wife. Then fall started, and my performance levels declined steadily into November. The numbers started to bounce back in December, and I feel as strong as I've felt in a long while.

I guess fall semester hit me harder than I realized.

In most ways, I feel like I'm back to normal now. I guess we will find out next week, when my attention turns to spring semester, both as department head and instructor. At least I get to teach programming languages, where I have a deep collection of session materials in hand and years of thinking and practice to buoy me up. Even with continued uncertainty due to the pandemic, I'm in pretty good shape.

Another effect of the summer and fall was that my already too-infrequent blogging slowed to a trickle. The fate of most blogs is a lack of drama. For me, blogging tends to flag when I am not reading or doing interesting work. The gradual expansion of administrative duties over the last few years has certainly taken its toll. But teaching a new course usually energizes me and leads to more regularly writing here. That didn't happen this fall.

With the semester now over, I have a better sense of the stress I must have been feeling. It affected my sleep, my workouts, and my teaching. It's no surprise that it affected my writing, too.

One of my goals for the coming year is to seek the sort of conscious, intentional awakening of the senses that Gide alludes to the passage quoted by that blog post. I'm also going to pay better attention to the signs that the treadmill is moving too fast. Running faster isn't always the solution.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

November 29, 2020 2:26 PM

Speaking in a Second Language

From this enlightening article that was being passed around a while back:

Talking posed a challenge for me. While my Mandarin was strong for someone who had grown up in the US, I wasn't fluent enough to express myself in the way I wanted. This had some benefits: I had to think before I spoke. I was more measured. I was a better listener. But it was also frustrating, as though I'd turned into a person who was meek and slow on the uptake. It made me think twice about the Chinese speakers at work or school in the US whom I'd judged as passive or retiring. Perhaps they were also funny, assertive, flirtatious, and profane in their native tongue, as I am in mine.

When people in the US talk about the benefits of learning a second language, they rarely, if ever, mention the empathy one can develop for others who speak and work in in a second language. Maybe that's because so few of us Americans learn a foreign language well enough to reach this level of enlightenment.

I myself learned just enough German in school to marvel at the accomplishment of exchange students studying here in their second language, knowing that I was nowhere near ready to live and study in a German-speaking land. Marvel, though, is not quite as valuable in this context as empathy.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

November 28, 2020 11:04 AM

How Might A Program Help Me Solve This Problem?

Note: The following comes from the bottom of my previous post. It gets buried there beneath a lot of code and thinking out loud, but it's a message that stands on its own.


I demo'ed a variation of my database-briven passphrase generator to my students as we closed the course last week. It let me wrap up my time with them by reminding them that they are developing skills that can change how they see every problem they encounter in the future.

Knowing how to write programs gives you a new power. Whenever you encounter a problem, you can ask yourself, "How might a program help me solve this?"

The same is true for many more specialized CS skills. People who know how to create a language and implement an interpreter can ask themselves, "How might a language help me solve this problem?" That's one of the outcomes, I hope, of our course in programming languages.

The same is true for databases, too. Whenever you encounter a problem, you can ask yourself, "Can a database help me solve this?"

Computer science students can use the tools they learn each semester to represent and interpret information. That's a power they can use to solve many problems. It's easy to lose sight of that fact during a busy semester and worth reflecting on in calmer moments.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

November 25, 2020 12:15 PM

Three Bears-ing a Password Generator in SQLite

A long semester -- shorter in time than usual by more than a week, but longer psychologically than any in a long time -- is coming to an end. Teaching databases for the first time was a lot of fun, though the daily grind of preparing so much new material in real time wore me down. Fortunately, I like to program enough that there were moments of fun scattered throughout the semester as I played with SQLite for the first time.

In the spirit of the Three Bears pattern, I looked for opportunities all semester to use SQLite to solve a problem. When I read about the Diceware technique for generating passphrases, I found one.

Diceware is a technique for generating passphrases using dice to select words from the "Diceware Word List", in which each word is paired with a five digit number. All of the digits are between one and six, so five dice rolls are all you need to select a word from the list. Choose a number of words for the passphrase, roll your dice, and select your words.

The Diceware Word List is a tab-separated file of dice rolls and words. SQLite can import TSV data directly into a table, so I almost have a database. I had to preprocess the file twice to make it importable. First, the file is wrapped as a PGP signed message, so I stripped the header and footer by hand, to create diceware-wordlist.txt.

Second, some of the words in this list contain quote characters. Like many applications, SQLite struggles with CSV and TSV files that contain embedded quote characters. There may be some way to configure it to handle these files gracefully, but I didn't bother looking for one. I just replaced the ' and " characters with _ and __, respectively:

    cat diceware-wordlist.txt \
      | sed "s/\'/_/g"        \
      | sed 's/\"/__/g'       \
      > wordlist.txt

Now the file is ready to import:

    sqlite> CREATE TABLE WordList(
       ...>    diceroll CHAR(5),
       ...>    word VARCHAR(30),
       ...>    PRIMARY KEY(diceroll)
       ...>    );

sqlite> .mode tabs sqlite> .import 'wordlist.txt' WordList

sqlite> SELECT * FROM WordList ...> WHERE diceroll = '11113'; 11113 a_s

That's one of the words that used to contain an apostrophe.

So, I have a dice roll/word table keyed on the dice roll. Now I want to choose words at random from the table. To do that, I needed a couple of SQL features we had not used in class: random numbers and string concatenation. The random() function returns a big integer. A quick web search showed me this code to generate a random base-10 digit:

    SELECT abs(random())%10
    FROM (SELECT 1);
which is easy to turn into a random die roll:
    SELECT 1+abs(random())%6
    FROM (SELECT 1);

I need to evaluate this query repeatedly, so I created a view that wraps the code in what acts, effectively, a function:

    sqlite> CREATE VIEW RandomDie AS
       ...>   SELECT 1+abs(random())%6 AS n
       ...>   FROM (SELECT 1);

Aliasing the random value as 'n' is important because I need to string together a five-roll sequence. SQL's concatenation operator helps there:

    SELECT 'Eugene' || ' ' || 'Wallingford';

I can use the operator to generate a five-character dice roll by selecting from the view five times...

    sqlite> SELECT n||n||n||n||n FROM RandomDie;
    sqlite> SELECT n||n||n||n||n FROM RandomDie;

... and then use that phrase to select random words from the list:

    sqlite> SELECT word FROM WordList
       ...> WHERE diceroll =
       ...>         (SELECT n||n||n||n||n FROM RandomDie);

Hurray! Diceware defaults to three-word passphrases, so I need to do this three times and concatenate.

This won't work...

    sqlite> SELECT word, word, word FROM WordList
       ...> WHERE diceroll =
       ...>         (SELECT n||n||n||n||n FROM RandomDie);
... because the dice roll is computed only once. A view can help us here, too:
    sqlite> CREATE VIEW OneRoll AS
       ...>   SELECT word FROM WordList
       ...>   WHERE diceroll =
       ...>           (SELECT n||n||n||n||n FROM RandomDie);

OneRoll acts like a table that returns a random word:

    sqlite> SELECT word FROM OneRoll;
    sqlite> SELECT word FROM OneRoll;
    sqlite> SELECT word FROM OneRoll;

Almost there. Now, this query generates three-word passphrases:

    sqlite> SELECT Word1.word || ' ' || Word2.word || ' ' || Word3.word FROM
       ...>   (SELECT * FROM OneRoll) AS Word1,
       ...>   (SELECT * FROM OneRoll) AS Word2,
       ...>   (SELECT * FROM OneRoll) AS Word3;
    eagle crab pinch

Yea! I saved this query in gen-password.sql and saved the SQLite database containing the table WordList and the views RandomDie and OneRoll as diceware.db. This lets me generate passphrases from the command line:

    $ sqlite3 diceware.db < gen-password.sql
    ywca maine over
Finally, I saved that command in a shell script named gen-password, and I now have passphrase generator ready to use with a few keystrokes. Success.

Yes, this is a lot of work to get a simple job done. Maybe I could do better with Python and a CSV reader package, or some other tools. But that wasn't the point. I was revisiting SQL and learning SQLite with my students. By overusing the tools, I learned them both a little better and helped refine my sense of when they will and won't be helpful to me in the future. So, success.


I demo'ed a variation of this to my students on the last day of class. It let me wrap up my time with them by pointing out that they are developing skills which can change how they see every problem they encounter in the future.

Knowing how to write programs gives you a new power. Whenever you encounter a problem, you can ask yourself, "How might a program help me solve this?" I do this daily, both as faculty member and department head.

The same is true for many more specialized CS skills. People who know how to create a language and implement an interpreter can ask themselves, "How might a language help me solve this problem?" That's one of the outcomes, I hope, of our course in programming languages.

The same is true for databases. When I came across a technique for generating passphrases, I could ask myself, "How might a database help me build a passphrase generator?"

Computer science students can use the tools they learn each semester to represent and interpret information. That's a power they can use to solve many problems. It's easy to lose sight of this incredible power during a hectic semester, and worth reflecting on in calmer moments after the semester ends.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

October 19, 2020 2:27 PM

An "Achievement Gap" Is Usually A Participation Gap

People often look at the difference between the highest-rated male chess player in a group and the highest-rated female chess player in the same group and conclude that there is a difference between the abilities of men and women to play chess, despite the fact that there are usually many, many more men in the group than women. But that's not even good evidence that there is an achievement gap. From What Gender Gap in Chess?:

It's really quite simple. Let's say I have two groups, A and B. Group A has 10 people, group B has 2. Each of the 12 people gets randomly assigned a number between 1 and 100 (with replacement). Then I use the highest number in Group A as the score for Group A and the highest number in Group B as the score for Group B. On average, Group A will score 91.4 and Group B 67.2. The only difference between Groups A and B is the number of people. The larger group has more shots at a high score, so will on average get a higher score. The fair way to compare these unequally sized groups is by comparing their means (averages), not their top values. Of course, in this example, that would be 50 for both groups -- no difference!

I love this paragraph. It's succinct and uses only the simplest ideas from probability and statistics. It's the sort of statistics that I would hope our university students learn in their general education stats course. While learning a little math, students can also learn about an application that helps us understand something important in the world.

The experiment described is also simple enough for beginning programmers to code up. Over the years, I've used problems like this with intro programming students in Pascal, Java, and Python, and with students learning Scheme or Racket who need some problems to practice on. I don't know whether learning science supports my goal, but I hope that this sort of problem (with suitable discussion) can do double duty for learners: learn a little programming, and learn something important about the world.

With educational opportunities like this available to us, we really should be able to turn graduates who have a decent understanding of why so many of our naive conclusions about the world are wrong. Are we putting these opportunities to good use?

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

September 18, 2020 2:50 PM

If You Want to Create Greatness, Encourage Everyone

I read two passages in the last few days that echo one another. First, I read this from Wallace Shawn, in a Paris Review interview:

But my God, without writers, humanity might be trapped in a swamp of idiotic, unchanging provincial clichés. Yes, there are writers who merely reinforce people's complacency, but a writer like Rachel Carson inspired the activism of millions, and writers like Lady Murasaki, Milton, and Joyce have reordered people's brains! And for any writers to exist at all, there must surely be a tradition of writing. Maybe in order for one valuable writer to exist, there must be a hundred others who aren't valuable at all, but it isn't possible at any given moment for anyone to be sure who the valuable one is.

Then, in his response to Marc Andreessen's "It's Time to Build", Tanner Greer writes:

To consistently create brilliant poets, you need a society awash in mediocre, even tawdry poetry. Brilliant minds will find their way towards poem writing when poem writing and poem reading is the thing that people do.

I once blogged briefly about The Art of Fear tells the story of an artist sketching hundreds of roosters, which laid the foundation for creating a single sketch for his client. For us as individuals, this means that "talent is rarely distinguishable, over the long run, from perseverance and lots of hard work." As Richard Gabriel often says, "Talent determines only how fast you get good, not how good you get". Volume creates the conditions under which quality can appear.

Shawn and Greer remind us that the same dynamic applies at the scale of a culture. A community that produces many writers has a better chance to produce great writers. When the community values writers, it increases the chances that someone will do the work necessary to becoming a writer. The best way to produce a lot of writers is to have a tradition that welcomes, even encourages, all members of the community to write, even if they aren't great.

The same applies to other forms of achievement, too. In particular, I think it applies to programming.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

August 22, 2020 4:09 PM

Learning Something You Thought You Already Knew

Sandi Metz's latest newsletter is about the heuristic not to name a class after the design pattern it implements. Actually, it's about a case in which Metz wanted to name a class after the pattern it implements in her code and then realized what she had done. She decided that she either needed to have a better reason for doing it than "because it just felt right" or she needed practice what she preaches to the rest of us. What followed was some deep thinking about what makes the rule a good one to follow and her efforts to put her conclusions in writing for the benefit of her readers.

I recognize with Metz's sense of discomfort at breaking a rule when it feels right and her need to step back and understand the rule at a deeper level. Between her set up and her explanation, she writes:

I've built a newsletter around this rule not only because I believe that it's useful, but also because my initial attempts to explain it exposed deep holes in my understanding. This was a revelation. Had I not been writing a book, I might have hand-waved around these gaps in my knowledge forever.

People sometimes say, "If you you really want to understand something, teach it to others." Metz's story is a great example of why this is really true. I mean, sure, you can learn any new area and then benefit from explaining it to someone else. Processing knowledge and putting it in your own words helps to consolidate knowledge at the surface. But the real learning comes when you find yourself in a situation where you realize there's something you've taken for granted for months or for years, something you thought you knew, but suddenly you sense a deep hole lying under the surface of that supposed understanding. "I just know breaking the rule is the right thing to do here, but... but..."

I've been teaching long enough to have had this experience many times in many courses, covering many areas of knowledge. It can be terrifying, at least momentarily. The temptation to wave my hands and hurry past a student's question is enormous. To learn from teaching in these moments requires humility, self-awareness, and a willingness to think and work until you break through to that deeper understanding. Learning from these moments is what sets the best teachers and writers apart from the rest of us.

As you might guess from Metz's reaction to her conundrum, she's a pretty good teacher and writer. The story in the newsletter is from the new edition of her book "99 Bottles of OOP", which is now available. I enjoyed the first edition of "99 Bottles" and found it useful in my own teaching. It sounds like the second edition will be more than a cleanup; it will have a few twists that make it a better book.

I'm teaching our database systems course for the first time ever this fall. This is a brand new prep for me: I've never taught a database course before, anywhere. There are so many holes in my understanding, places where I've internalized good practices but don't grok them in the way an expert does. I hope I have enough humility and self-awareness this semester to do my students right.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

July 01, 2020 3:19 PM

Feeling Unstuck Amid the Pandemic

Rands recently wrote about his work-from-home routine. I love the idea of walking around a large wooded yard while doing audio meetings... One of his reasons for feeling so at ease struck a chord with me:

Everyone desperately wants to return to normality. I am a professional optimist, but we are not returning to normal. Ever. This is a different forever situation, and the sooner we realize that and start to plan accordingly, the sooner we will feel unstuck.

I have written or spoken a variation of this advice so many times over my fifteen years as department head, most often in the context of state funding and our university budget.

Almost every year for my first decade as head, we faced a flat or reduced budget, and every time several university colleagues expressed a desire to ride the storm out: make temporary changes to how we operate and wait for our budgets to return to normal. This was usually accompanied by a wistful desire that we could somehow persuade legislators of our deep, abiding value and thus convince them to allocate more dollars to the university or, failing that, that new legislators some future legislature would have different priorities.

Needless to say, the good old days never returned, and our budget remained on a downward slide that began in the late 1990s. This particular form of optimism was really avoidance of reality, and it led to many people living in a state of disappointment and discomfort for years. Fortunately, over the last five or ten years, most everyone has come to realize that what we have now is normal and has begun to plan accordingly. It is psychologically powerful to accept reality and begin acting with agency.

As for the changes brought on by the pandemic, I must admit that I am undecided about how much of what has changed over the last few months will be the normal way of the university going forward.

My department colleagues and I have been discussing how the need for separation among students in the classroom affects how we teach. Our campus doesn't have enough big rooms for everyone to move each class into a room with twice the capacity, so most of us are looking at ways to teach hybrid classes, with only half of our students in the classroom with us on any given day. This makes most of us sad and even a little depressed: how can we teach our courses as well as we always have in the past when new constraints don't allow us to do what we have optimized our teaching to do?

I have started thinking of the coming year in terms of hill climbing, an old idea from AI. After years of hard work and practice, most of us are at a local maximum in our teaching. The pandemic has disoriented us by dropping us at a random point in the environment. The downside of change in position is that we are no longer at our locally-optimal point for teaching our courses. The upside is that we get to search again under new conditions. Perhaps we can find a new local maximum, perhaps even one higher than our old max. If not, at least we have conducted a valuable experiment under trying conditions and can use what we learn going forward.

This analogy helps me approach my new course with more positive energy. A couple of my colleagues tell me it has helped them, too.

As many others have noted, the COVID-19 crisis has accelerated a few changes that were already taking place in our universities, in particular in the use of digital technology to engage students and to replace older processes. Of the other changes we've seen, some will certainly stick, but I'm not sure anyone really knows which ones. Part of the key to living with the uncertainty is not to tie ourselves too closely to what we did before.

Posted by Eugene Wallingford | Permalink | Categories: General, Managing and Leading, Teaching and Learning

June 17, 2020 3:53 PM

Doing Concatenative Programming in a Spreadsheet

a humble spreadsheet cell

It's been a long time since I was excited by a new piece of software the way I was excited by Loglo, Avi Bryant's new creation. Loglo is "LOGO for the Glowforge", an experimental programming environment for creating SVG images. That's not a problem I need to solve, but the way Loglo works drew me in immediately. It consists of a stack programming language and a set of primitives for describing vector graphics, integrated into a spreadsheet interface. It's the use of a stack language to program a spreadsheet that excites me so much.

Actually, it's the reverse relationship that really excites me: using a spreadsheet to build and visualize a stack-based program. Long-time readers know that I am interested in this style of programming (see Summer of Joy for a post from last year) and sometimes introduce it in my programming languages course. Students understand small examples easily enough, but they usually find it hard to grok larger programs and to fully appreciate how typing in such a language can work. How might Loglo help?

In Loglo, a cell can refer to the values produced by other cells in the familiar spreadsheet way, with an absolute address such as "a1" or "f2". But Loglo cells have two other ways to refer to other cell's values. First, any cell can access the value produced by the cell to its left implicitly, because Loglo leaves the result of a cell's computation sitting on top of the stack. Second, a cell can access the value produced by the cell above it by using the special variable "^". These last two features strike me as a useful way for programmers to see their computations grow over time, which can be an even more powerful mode of interaction for beginners who are learning this programming style.

Stack-oriented programming of this sort is concatenative: programs are created by juxtaposing other programs, with a stack of values implicitly available to every operator. Loglo uses the stack as leverage to enable programmers to build images incrementally, cell by cell and row by row, referring to values on the stack as well as to predecessor cells. The programmer can see in a cell the value produced by a cumulative bit of code that includes new code in the cell itself. Reading Bryant's description of programming in Loglo, it's easy to see how this can be helpful when building images. I think my students might find it helpful when learning how to write concatenative programs or learning how types and programs work in a concatenative language.

For example, here is a concatenative program that works in Loglo as well as other stack-based languages such as Forth and Joy:

 2 3 + 5 * 2 + 6 / 3 /

Loglo tells us that it computes the value 1.5:

a stack program in Loglo

This program consists of eleven tokens, each of which is a program in its own right. More interestingly, we can partition this program into smaller units by taking any subsequences of the program:

 2 3 + 5 *   2 + 6 /   3 /
 ---------   -------   ---
These are the programs in cells A1, B1, and C1 of our spreadsheet. The first computes 25, the second uses that value to compute 4.5, and the third uses the 4.5 to compute 1.5. Notice that the programs in cells B1 and C1 require an extra value to do their jobs. They are like functions of one argument. Rather than pass an argument to the function, Loglo allows it to read a value from the stack, produced by the cell to its left.

a partial function in Loglo

By making the intermediate results visible to the programmer, this interface might help programmers better see how pieces of a concatenative program work and learn what the type of a program fragment such as 2 + 6 / (in cell B1 above) or 3 / is. Allowing locally-relative references on a new row will, as Avi points out, enable an incremental programming style in which the programmer uses a transformation computed in one cell as the source for a parameterized version of the transformation in the cell below. This can give the novice concatenative programmer an interactive experience more supportive than the usual REPL. And Loglo is a spreadsheet, so changes in one cell percolate throughout the sheet on each update!

Am I the only one who thinks this could be a really cool environment for programmers to learn and practice this style of programming?

Teaching concatenative programming isn't a primary task in my courses, so I've never taken the time to focus on a pedagogical environment for the style. I'm grateful to Avi for demonstrating a spreadsheet model for stack programs and stimulating me to think more about it.

For now, I'll play with Loglo as much as time permits and think more about its use, or use of a tool like it, in my courses. There are couple of features I'll have to get used to. For one, it seems that a cell can access only one item left on the stack by its left neighbor, which limits the kind of partial functions we can write into cells. Another is that named functions such as rotate push themselves onto the stack by default and thus require a ! to apply them, whereas operators such as + evaluate by default and thus require quotation in a {} block to defer execution. (I have an academic's fondness for overarching simplicity.) Fortunately, these are the sorts of features one gets used to whenever learning a new language. They are part of the fun.

Thinking beyond Loglo, I can imagine implementing an IDE like this for my students that provides features that Loglo's use cases don't require. For example, it would be cool to enable the programmer to ctrl-click on a cell to see the type of the program it contains, as well as an option to see the cumulative type along the row or built on a cell referenced from above. There is much fun to be had here.

To me, one sign of a really interesting project is how many tangential ideas flow out of it. For me, Loglo is teeming with ideas, and I'm not even in its target demographic. So, kudos to Avi!

Now, back to administrivia and that database course...

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

June 11, 2020 1:02 PM

Persistence Wins, Even For Someone Like You

There's value to going into a field that you find difficult to grasp, as long as you're willing to be persistent. Even better, others can benefit from your persistence, too.

In an old essay, James Propp notes that working in a field where you lack intuition can "impart a useful freedom from prejudice". Even better...

... there's value in going into a field that you find difficult to grasp, as long as you're willing to be really persistent, because if you find a different way to think about things, something that works even for someone like you, chances are that other people will find it useful too.

This reminded me of a passage in Bob Nystroms's post about his new book, Crafting Interpreters. Nystrom took a long time to finish the book in large part because he wanted the interpreter at the end of each chapter to compile and run, while at the same time growing into the interpreter discussed in the next chapter. But that wasn't the only reason:

I made this problem harder for myself because of the meta-goal I had. One reason I didn't get into languages until later in my career was because I was intimidated by the reputation compilers have as being only for hardcore computer science wizard types. I'm a college dropout, so I felt I wasn't smart enough, or at least wasn't educated enough to hack it. Eventually I discovered that those barriers existed only in my mind and that anyone can learn this.

Some students avoid my compilers course because they assume it must be difficult, or because friends said they found it difficult. Even though they are CS majors, they think of themselves as average programmers, not "hardcore computer science wizard types". But regardless of the caliber of the student at the time they start the course, the best predictor of success in writing a working compiler is persistence. The students who plug away, working regularly throughout the two-week stages and across the entire project, are usually the ones who finish successfully.

One of my great pleasures as a prof is seeing the pride in the faces of students who demo a working compiler at the end of the semester, especially in the faces of the students who began the course concerned that they couldn't hack it.

As Propp points out in his essay, this sort of persistence can pay off for others, too. When you have to work hard to grasp an idea or to make something, you sometimes find a different way to think about things, and this can help others who are struggling. One of my jobs as a teacher is to help students understand new ideas and use new techniques. That job is usually made easier when I've had to work persistently to understand the idea myself, or to find a better way to help the students who teach me the ways in which they struggle.

In Nystrom's case, his hard work to master a field he didn't grasp immediately pays of for his readers. I've been following the growth of Crafting Interpreters over time, reading chapters in depth whenever I was able. Those chapters were uniformly easy to read, easy to follow, and entertaining. They have me thinking about ways to teach my own course differently, which is probably the highest praise I can give as a teacher. Now I need to go back and read the entire book and learn some more.

Teaching well enough that students grasp what they thought was not graspable and do what they thought was not doable is a constant goal, rarely achieved. It's always a work in progress. I have to keep plugging away.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

May 22, 2020 3:34 PM

What Good Can Come From All This?

Jerry Seinfeld:

"What am I really sick of?" is where innovation begins.

Steve Wozniak:

For a lot of entrepreneurs, they see something and they say, "I have to have this," and that will start them building their own.

Morgan Housel:

Necessity is the mother of invention, so our willingness to solve problems is about to surge.

A lot of people are facing a lot of different stresses right now, with the prospect that many of those stresses will continue on into the foreseeable future. For instance, I know a lot of CS faculty who are looking at online instruction and remote learning much carefully now that they may be doing it again in the fall. Many of us have some things to learn, and some real problems need to be solved.

"What am I really sick of?" can turn the dial up on our willingness to solve problems that have been lingering in the background for a while. Let's hope that some good can come from the disruption.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

May 18, 2020 4:10 PM

Not Receiving Negative Feedback Makes It Hard to Improve

As a financial writer for Forbes and the Wall Street Journal, Jason Zweig has received a lot of letters from readers, many of them forcefully suggesting that his columns could be better. In this interview, he speaks calmly about processing negative feedback:

... when you get negative feedback, you have to sort it. You can't just take all negative feedback and throw it in the "I'm not reading this" bucket. You have to go through it. And you have to say: "Is this person, who says I'm wrong, right or wrong?" Because if the person says you're wrong, and is wrong, then how does that hurt you? But if the person who says you're wrong is right, it's devastating to you if you don't listen.
It's not about winning. It's about learning.

I know profs who refuse to read their student assessments because it's too hard emotionally to deal with negative feedback. I understand the temptation... There are semesters when thirty-nine reviews are positive, yet the one negative review lodges itself in my brain and won't let go. Even after decades of teaching, it can be hard to shake off those comments immediately. And when there many comments that are "constructive" or just plain negative, well, reading the assessments can really demoralize.

But as Zweig says, closing myself off to the feedback is ultimately a losing proposition. Sometimes I assess a comment and decide that it's off the mark, or the result of singular event or experience and therefore isn't worth sweating over. But what about when the reviewer is right? Or when there's a kernel of truth in an otherwise unnecessarily personal comment? Ignoring the truth doesn't do me any good. I want to get better.

I did not receive student assessments this spring. When the university moved to remote instruction suddenly, the administration and faculty agreed to suspended assessments for the semester, with the idea that teaching and learning would both be a bit bumpier than usual under the extreme conditions. Just before the last week of the term, they agreed to bring optional assessments back purely for the prof's personal use, but by then I decided to pass. Some of my students provided some helpful feedback, including constructive criticism, all on their own.

I'll actually miss reading my assessments this month, if not the sudden spike in my blood pressure that sometimes accompanies them. Students are usually helpful and surprisingly generous in their evaluations, and I still usually learn a lot from the positive ones and the negative ones alike.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

May 16, 2020 11:33 AM

Woz Sez: Take Some Time To Get To Know Your Program Better

Steve Wozniak in Founders at Work:

If you can just quickly whip something out and it's done, maybe it's time, once in a while, to think and think and think, "Can I make it better than it is, a little superior?" What that does is not necessarily make the product better in the end, but it brings you closer to the product, and your own head understands it better. Your neurons have gone through the code you wrote, or the circuits you designed, have gone through it more times, and it's just a little more solidly in your head and once in a while you'll wake up and say, "Oh my God, I just realized a bug that's in there, something I hadn't thought of."

Or, if you have to modify something, or add something new, you can do it very quickly when it's all in your head. You don't have to pull out the listing and find out where and maybe make a mistake. You don't make as many mistakes.

Many programmers know this feeling, of having a program in your head and moving in sync with it. When programs are small, it's easy for me to hold a program in my head. As it grows larger and spreads out over many functions, classes, and files, I have to live with it over an extended period of time. Taking one of Woz's dives into the just to work on it is a powerful way to refresh the feeling.

Beginning programmers have to learn this feeling, I think, and we should help them. In the beginning, my students know what it's like to have a program in their head all at once. The programs are small, and the new programmer has to pay attention to every detail. As programs grow, it becomes harder for them. They work locally to make little bits of code work, and suddenly they have a program that does fit naturally in their head. But they don't have the luxury of time to do what Woz suggests, because they are on to the next reading assignment, the next homework, the next class across campus.

One of the many reasons I like project courses such as my compiler course is that students live with the same code for an entire semester. Sure, they finish the scanner and move on to the parser, and then onto a type checker and a code generator, but they use their initial stages every day and live with the decisions they made. It's not uncommon for a student to tell me 1/2 or 3/4 of the way through the course, "I was looking at our scanner (or parser) the other day, and now I understand why we were having that problem I told you about. I'm going to fix it over Thanksgiving break."

In my programming languages course, we close with a three week three assignment project building an interpreter. I love when a student submitting on Part 3 says, "Hey, I just noticed that some parts of Part 2 could be better. I hope you don't mind that I improved that, too." Um, no. No, I don't mind at all. They get it.

It's easy to shortchange our students with too many small projects. I like most of my courses to have at least some code grow over the course of the semester. Students may not have the luxury of a lot of free time, but at least they work in proximity to their old code for a while. Serendipity may strike if we create the right conditions for it.

I have already begun to think about how I can foster this in my new course this fall. I hope to design it into the course upfront.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

May 14, 2020 2:35 PM

Teaching a New Course in the Fall

I blogged weekly about the sudden switch to remote instruction starting in late March, but only for three weeks. I stopped mostly because my sense of disorientation had disappeared. Teaching class over Zoom started to feel more normal, and my students and I got back into the usual rhythm. A few struggled in ways that affected their learning and performance, and a smaller few thrived. My experience was mostly okay: some parts of my work suffered as I learned how to use tools effectively, but not having as many external restrictions on my schedule offset the negatives. Grades are in, summer break begins to begin, and at least some things are right with the world.

Fall offers something new for me to learn. My fall compilers course had a lower enrollment than usual and, given the university's current financial situation, I had to cancel it. This worked out fine for the department, though, as one of our adjunct instructors asked to take next year off in order to deal with changes in his professional and personal lives. So there was a professor in need of a course, and a course in need of a professor: Database Systems.

Databases is one of the few non-systems CS courses that I have never taught as a prof or as a grad student. It's an interesting course, mixing theory and design with a lot of practical skills that students and employers prize. In this regard, it's a lot of like our OO design and programming course in Java, only with a bit more visible theory. I'm psyched to give it a go. At the very least, I should be able to practice some of those marketable skills and learn some of the newer tools involved.

As with all new preps, this course has me looking for ideas. I'm aware of a few of the standard texts, though I am hoping to find a good open-source text online, or a set of online materials out of which to assemble the readings my students will need for the semester. I'm going to be looking scouting for all the other materials I need to teach the course as well, including examples, homework assignments, and projects. I tend to write a lot of my own stuff, but I also like to learn from good courses and good examples already out there. Not being a database specialist, I am keen to see what specialists think is important, beyond what we find in traditional textbooks.

Then there is the design of the course itself. Teaching a course I've never taught before means not having an old course design to fall back on. This means more work, of course, but is a big win for curious mind. Sometimes, it's fun to start from scratch. I have always found instructional design fascinating, much like any kind of design, and building a new course leaves open a lot of doors for me to learn and to practice some new skills.

COVID-19 is a big part of why I am teaching this course, but it is not done with us. We still do not know what fall semester will look like, other than to assume that it won't look like a normal semester. Will be on campus all semester, online all semester, or a mix of both? If we do hold instruction on campus, as most universities are hoping to do, social distancing requirements will require us to do some things differently, such as meeting students in shifts every other day. This uncertainty suggests that I should design a course that depends less on synchronous, twice-weekly, face-to-face direct instruction and more on ... what?

I have a lot to learn about teaching this way. My university is expanding its professional development offerings this summer and, in addition to diving deep into databases and SQL, I'll be learning some new ways to design a course. It's exciting but also means a bit more teaching prep than usual for my summer.

This is the first entirely new prep I've taught in a while. I think the most recent was the fall of 2009, when I taught Software Engineering for the first and only time. Looking back at the course website reminds me that I created this delightful logo for the course:

course logo for Software Engineering, created using YUML

So, off to work I go. I could sure use your help. Do you know of model database courses that I should know about? What database concepts and skills should CS graduates in 2021 know? What tools should they be able to use? What has changed in the world since I last took database courses that must be reflected in today's database course? Do you know of a good online textbook for the course, or a print book that my students would find useful and be willing to pay for?

If you have any ideas to share, feel free to email me or contact me on Twitter. If not for me, do it for my students!

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

May 10, 2020 2:16 PM

Software Can Make You Feel Alive, or It Can Make You Feel Dead

This week I read one of Craig Mod's old essays and found a great line, one that everyone who writes programs for other people should keep front of mind:

When it comes to software that people live in all day long, a 3% increase in fun should not be dismissed.

Working hard to squeeze a bit more speed out of a program, or to create even a marginally better interaction experience, can make a huge difference to someone who uses that program everyday. Some people spend most of their professional days inside one or two pieces of software, which accentuates further the human value of Mod's three percent. With shelter-in-place and work-from-home the norm for so many people these days, we face a secondary crisis of software that is no fun.

I was probably more sensitive than usual to Mod's sentiment when I read it... This week I used Blackboard for the first time, at least my first extended usage. The problem is not Blackboard, of course; I imagine that most commercial learning management systems are little fun to use. (What a depressing phrase "commercial learning management system" is.) And it's not just LMSes. We use various PeopleSoft "campus solutions" to run the academic, administrative, and financial operations on our campus. I always feel a little of my life drain away whenever I spend an hour or three clicking around and waiting inside this large and mostly functional labyrinth.

It says a lot that my first thought after downloading my final exams on Friday morning was, "I don't have to login to Blackboard again for a good long while. At least I have that going for me."

I had never used our LMS until this week, and then only to create a final exam that I could reliably time after being forced into remote teaching with little warning. If we are in this situation again in the fall, I plan to have an alternative solution in place. The programmer in me always feels an urge to roll my own when I encounter substandard software. Writing an entire LMS is not one of my life goals, so I'll just write the piece I need. That's more my style anyway.

Later the same morning, I saw this spirit of writing a better program in a context that made me even happier. The Friday of finals week is my department's biennial undergrad research day, when students present the results of their semester- or year-long projects. Rather than give up the tradition because we couldn't gather together in the usual way, we used Zoom. One student talked about alternative techniques for doing parallel programming in Python, and another presented empirical analysis of using IR beacons for localization of FIRST Lego League robots. Fun stuff.

The third presentation of the morning was by a CS major with a history minor, who had observed how history profs' lectures are limited by the tools they had available. The solution? Write better presentation software!

As I watched this talk, I was proud of the student, whom I'd had in class and gotten to know a bit. But I was also proud of whatever influence our program had on his design skills, programming skills, and thinking. This project, I thought, is a demonstration of one thing every CS student should learn: We can make the tools we want to use.

This talk also taught me something non-technical: Every CS research talk should include maps of Italy from the 1300s. Don't dismiss 3% increases in fun wherever they can be made.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

April 29, 2020 4:45 PM

Teaching Class is Like Groundhog Day

As I closed down my remote class session yesterday, I felt a familiar feeling... That session can be better! I've been using variations of this session, slowly improving it, for a few years now, and I always leave the classroom thinking, "Wait 'til next time." I'm eager to improve it now and iterate, trying it again tomorrow. Alas, tomorrow is another day, with another class session all its own. Next time is next year.

Bill Murray, suspicion of Groundhog Day

I feel this way about most of the sessions in most of my courses. Yesterday, it occurred to me that this must be what Phil Connors feels like in Groundhog Day.

Phil wakes up every day in the same place and time as yesterday. Part way through the film, he decides to start improving himself. Yet the next morning, there he is again, in the same place and time as yesterday, a little better but still flawed, in need of improvement.

Next spring, when I sit down to prep for this session, it will be like hitting that alarm clock and hearing Sonny and Cher all over again.

I told my wife about my revelation and my longing: If only I could teach this session 10,000 times, I'd finally get it right. You know what she said?

"Think how your students must feel. If they could do that session 10,000 times, they'd feel like they really got it, too."

My wife is wise. My students and I are in this together, getting a little better each day, we hope, but rarely feeling like we've figured all that much out. I'll keep plugging away, Phil Connors as CS prof. "Okay, campers, rise and shine..." Hopefully, today I'll be less wrong than yesterday. I wish my students the same.

Who knows, one of these days, maybe I'll leave a session and feel as Phil does in the last scene of the film, when he wakes up next to his colleague Rita. "Do you know what today is? Today is tomorrow. It happened. You're here." I'm not holding my breath, though.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

April 19, 2020 4:10 PM

I Was a Library Kid, Too

Early in this Paris Review interview, Ray Bradbury says, "A conglomerate heap of trash, that's what I am." I smiled, because that's what I feel like sometimes, both culturally and academically. Later he confessed something that sealed my sense of kinship with him:

I am a librarian. I discovered me in the library. I went to find me in the library. Before I fell in love with libraries, I was just a six-year-old boy. The library fueled all of my curiosities, from dinosaurs to ancient Egypt.

the bookshelf in my home office

I was a library kid, too. I owned a few books, but I looked forward to every chance we had to go to the library. My grade school had books in every classroom, and my teachers shared their personal books with those of us who so clearly loved to read. Eventually my mom took me and my siblings to the Marion County public to get a library card, and the world of books available seemed limitless. When I got to high school, I spent free time before and after classes wandering the stacks, discovering science fiction, Vonnegut and Kafka and Voltaire, science and history. The school librarian got used to finding me in the aisles at times. She became as much a friend as any high school teacher could. So many of my friends have shelves and shelves of books; they talk about their addiction to Amazon and independent bookstores. But almost all of the books I have at home fit in a single bookshelf (at right). One of them is Bradbury's The Martian Chronicles, which I discovered in high school.

I do have a small chess library on another shelf across the room and a few sports books, most from childhood, piled nearby. I tried to get rid of the sports books once, in a fit of Marie Kondo-esque de-cluttering, but I just couldn't. Even I have an attachment to the books I own. Having so few, perhaps my attraction is even stronger than it might otherwise be, subject to some cosmic inverse square law of bibliophilia.

At my office, I do have two walls full of books, mostly textbooks accumulated over my years as a professor. When I retire, though, I'll keep only one bookcase full of those -- a few undergrad CS texts, yes, but mostly books I purchased because they meant something to me. Gödel, Escher, Bach. Metamagical Themas. Models of My Life. A few books about AI. These are books that helped me find me.

After high school, I was fortunate to spend a decade in college as an undergraduate and grad student. I would not trade those years for anything; I learned a lot, made friends with whom I remain close, and grew up. Bradbury, though, continued his life as an autodidact, going to the public library three nights a week for a decade, until he got married.

So I graduated from the library, when I was twenty-seven. I discovered that the library is the real school.

Even though I spent a decade as a student in college and now am a university prof, the library remains my second home. I rarely buy books to this day; I don't remember my last purchase. The university library is next to my office building, and I make frequent trips over in the afternoons. They give me a break from work and a chance to pick up my next read. I usually spend a lot more time there than necessary, wandering the stacks and exploring. I guess I'm still a library kid.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

April 14, 2020 3:53 PM

Going Online, Three-Plus Weeks In

First the good news: after three more sessions, I am less despondent than I was after Week Two. I have taken my own advice from Week One and lowered expectations. After teaching for so many years and developing a decent sense of my strengths and weaknesses in the classroom, this move took me out of my usual groove. It was easy to forget in the rush of the moment not to expect perfection, and not being able to interact with students in the same way created different emotions about the class sessions. Now that I have my balance back, things feel a bit more normal.

Part of what changed things for me was watching the videos I made of our class sessions. I quickly realized that these sessions are no worse than my usual classes! It may be harder for students to pay attention to the video screen for seventy-five minutes in the same way they might pay attention in the classroom, but my actual presentation isn't all that different. That was comforting, even as I saw that the videos aren't perfect.

Another thing that comforted me: the problems with my Zoom sessions are largely the same as the problems with my classroom sessions. I can fall into the habit of talking too much and too long unless I carefully design exercises and opportunities for students to take charge. The reduced interaction channel magnifies this problem slightly, but it doesn't create any new problems in principle. This, too, was comforting.

For example, I notice that some in-class exercises work better than others. I've always know this from my in-person course sessions, but our limited interaction bandwidth really exposes problems that are at the wrong level for where the students are at the moment (for me, usually too difficult, though occasionally too easy). I am also remembering the value of the right hint at the right moment and the value of students interacting and sharing with one another. Improving on these elements of my remote course should result in corresponding improvements when we move back to campus.

I have noticed one new problem: I tend to lose track of time more easily when working with the class in Zoom, which leads me to run short on time at the end of the period. In the classroom, I glance at a big analog clock on the wall at the back of the room and use that to manage my time. My laptop has a digital clock in the corner, but it doesn't seem to help me as much. I think this is a function of two parameters: First, the clock on my computer is less obtrusive, so I don't look at it as often. Second, it is a digital clock. I feel the geometry of analog time viscerally in a way that I don't with digital time. Maybe I'm just old, or maybe we all experience analog clocks in a more physical way.

I do think that watching my lectures can help me improve my teaching. After Week One, I wondered, "In what ways can going online, even for only a month and a half, improve my course and materials?" How might this experience make me a better teacher or lead to better online materials? I have often heard advice that I should record my lectures so that I could watch them with an experienced colleague, with an eye to identifying strengths to build on and weaknesses to improve on. Even without a colleague to help, this few weeks of recording gives me a library of sessions I can use for self-diagnosis and improvement.

Maybe this experience will have a few positives to counterbalance its obvious negatives.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

April 03, 2020 2:05 PM

Going Online, Two Weeks In

Earlier in the week I read this article by Jason Fried and circled these sentences:

Ultimately this major upheaval is an opportunity. This is a chance for your company, your teams, and individuals to learn a new skill. Working remotely is a skill.

After two weeks of the great COVID-19 school-from-home adventure, I very much believe that teaching remotely is a skill -- one I do not yet have.

Last week I shared a few thoughts about my first week teaching online. I've stopped thinking of this as "teaching online", though, because my course was not designed as an online course. It was pushed online, like so many courses everywhere, in a state of emergency. The result is a course that has been optimized over many years for face-to-face synchronous interaction being taken by students mostly asynchronously, without much face-to-face interaction.

My primary emotion after my second week teaching remotely is disappointment. Switching to this new mode of instruction was simple but not easy, at least not easy to do well. It was simple because I already have so much textual material available online, including detailed lecture notes. For students who can read the class notes, do exercises and homework problems, ask a few questions, and learn on their own, things seem to be going fine so far. (I'll know more as more work comes in for evaluation.) But approximately half of my students need more, and I have not figured out yet how best to serve them well.

I've now hosted four class sessions via Zoom for students who were available at class time and interested or motivated enough to show up. With the exception of one student, they all keep their video turned off, which offers me little or no visual feedback. Everyone keeps their audio turned off except when speaking, which is great for reducing the distraction of noises from everybody's homes and keyboards. The result, though, is an eerie silence that leaves me feeling as if I'm talking to myself in a big empty room. As I told my students on Thursday, it's a bit unnerving.

With so little perceptual stimulus, time seems to pass quickly, at least for me. It's easy to talk for far too long. I'm spared a bit by the fact that my classes intersperse short exposition by me with interactive work: I set them a problem, they work for a while, and then we debrief. This sort of session, though, requires the students to be engaged and up to date with their reading and homework. That's hard for me to expect of them under the best of conditions, let alone now when they are dispersed and learning to cope with new distractions.

After a few hours of trying to present material online, I very much believe that this activity requires skill and experience, of which I have little of either at this point. I have a lot of work to do. I hope to make Fried proud and use this as an opportunity to learn new skills.

I had expected by this point to have created more short videos that I could use to augment my lecture notes, for students who have no choice but to work on the course whenever they are free. Time has been in short supply, though, with everything on campus changing all at once. Perhaps if I can make a few more videos and flip the course a bit more, I will both serve those students better and find a path toward using our old class time better for the students who show up then and deserve a positive learning experience.

At level of nuts and bolts, I have already begun to learn some of the details of Panopto, Zoom, and our e-learning system. I like learning new tools, though the complications of learning them all at once and trying to use them at the same time makes me feel like a tech newbie. I guess that never changes.

The good news is that other parts of the remote work experience are going better, sometimes even well. Many administrative meetings work fine on Zoom, because they are mostly about people sharing information and reporting out. Most don't really need to be meetings anyway, and participating via Zoom is an improvement over gathering in a big room. As one administrator said at the end of one meeting recently, "This was the first council meeting online and maybe the shortest council meeting ever." I call that a success.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

March 27, 2020 2:31 PM

Going Online

It's been a long time since I've written here. In fits and starts over a couple of weeks, we went from "Wow, coronavirus is in the news a lot" to "all teaching is online through the end of summer, and Eugene has a lot of work to do". The new work included rearranging faculty candidates who were not allowed to fly to campus, looking to cover courses for a faculty who would be taking leave before the end of the semester, and -- of course -- moving my own course online.

This is new territory for me. I've never taught online, and I've never made videos for my students before. One bit of good news is that I have a lot of textual material online already: detailed lecture notes, exercises, homework assignments, every line of code we write or examine in class, all my exams, and a surprising amount of bonus material and extra reading. (Few students take advantage of the extra stuff, but I can't bring myself not provide links to it for the few who do.)

Over break, I made my first video, walking through a problem from our last homework assignment before break. I recorded three takes before having something I was willing to show students. It is rough and wordy, but not too bad for a first effort (well, v 1.03).

We now have a week of classes in the books. This is an unusual week in my course even under typical conditions. It consists a two-day in-class exercise on which students worked in groups of two or three to write a lexical addresser for a little language. With students segregated in their own apartments and hometowns, the intended group collaboration disappeared. Most of our students are still adjusting to the new learning conditions and figuring out how to take all of their courses online at home.

On Tuesday, I made one short video to review briefly the ideas about variable declarations and references that we had studied before break. After they watched the video, I turned them loose with my usual session notes, modified so that hints I would typically offer in class and document in a web page for later review hidden away on their own web pages. This way, students could work on the problem and only click on a hint when they needed a nudge. A few students showed up in a Zoom room and worked during the assigned class time, so I was able to interact with them in real time and answer questions. On Thursday, we re-oriented ourselves to the problem, and I live-coded a solution to the problem. I recorded the session for students to watch later, at their leisure.

I've already learned a bit, only one week in. The temptation to write a long piece of code and talk through the process is great. The students who braved Thursday's session let me know that they tuned out after a while, only to bring their attention back later, somewhat out of synch with my presentation. That's not much different from what happens in a long lecture, of course, but when I'm standing in a room with the students, I'm more likely to notice their boredom or distraction and step out of the lecture sooner. Talking to a few students in Zoom, especially when they have their video off, made it too easy to talk and talk without a break. Over many years of teaching face-to-face, I've learned how to mix class up a bit and not get into long ruts. I'll have to be more consciously aware of those lessons as I do demos over Zoom.

I'm still a little nervous about the rest of the semester, but also a little excited. In what ways can going online, even for only a month and a half, improve my course and materials? Putting session notes up over the years has already forced me to be more careful in how I write explanations and more detailed in the code I post. Now, with little or no face-to-face interaction (most students will come to a session after it ends), how will I need to improve my presentation and the materials I provide? How much will my inexperience making videos limit the level of quality I can achieve over six weeks?

For now, I plan to keep things as simple as possible. I'm not sure what technology my students have available to them at home, or the conditions under which they must work. I am still using email and my course website (a very simple static site that would feel at home in 2000) as my main ways to present material, and have added Zoom as a to interact with students in lieu of regular class time. I will make a few short video to demonstrate ideas, to augment the written material and give students another sensory input with which to learn. I don't expect the videos to be great, or even good, but I hope they help my students. I also hope that, with practice, I get better at making them.

Sadly, I won't be in a classroom with this group of students again this year. I'll miss that. They are good people, and I enjoy working with them. This is a strange way to end a school year, and a reminder of how fortunate I am to get to teach.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

February 29, 2020 11:19 AM

Programming Healthily

... or at least differently. From Inside Google's Efforts to Engineer Its Food for Healthiness:

So, instead of merely changing the food, Bakker changed the foodscape, ensuring that nearly every option at Google is healthy -- or at least healthyish -- and that the options that weren't stayed out of sight and out of mind.

This is how I've been thinking lately about teaching functional programming to my students, who have experience in procedural Python and object-oriented Java. As with deciding what we eat, how we think about problems and programs is mostly unconscious, a mixture of habit and culture. It is also something intimate and individual, perhaps especially for relative beginners who have only recently begun to know a language well enough to solve problems with some facility. But even for us old hands, the languages and mental tools we use to write programs can become personal. That makes change, and growth, hard.

In my last few offerings of our programming languages course, in which students learn Racket and functional style, I've been trying to change the programming landscape my students see in small ways whenever I can. Here are a few things I've done:

  • I've shrunk the set of primitive functions that we use in the first few weeks. A larger set of tools offers more power and reach, but it also can distract. I'm hoping that students can more quickly master the small set of tools than the larger set and thus begin to feel more accomplished sooner.

  • We work for the first few weeks on problems with less need for the tools we've moved out of sight, such as local variables and counter variables. If a program doesn't really benefit from a local variable, students will be less likely to reach for one. Instead, perhaps, they will reach for a function that can help them get closer to their goal.

  • In a similar vein, I've tried to make explicit connections between specific triggers ("We're processing a list of data, so we'll need a loop.") with new responses ("map can help us here."). We then follow up these connections with immediate and frequent practice.

By keeping functional tools closer at hand, I'm trying to make it easier for these tools to become the new habit. I've also noticed how the way I speak about problems and problem solving can subtly shape how students approach problems, so I'm trying to change a few of my own habits, too.

It's hard for me to do all these things, but it's harder still when I'm not thinking about them. This feels like progress.

So far students seem to be responding well, but it will be a while before I feel confident that these changes in the course are really helping students. I don't want to displace procedural or object-oriented thinking from their minds, but rather to give them a new tool set they can bring out when they need or want to.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

February 23, 2020 1:14 PM

One Way I'm Like Tom Waits

At one point in this conversation between Elvis Costello and Tom Waits, the two songwriters discuss some of the difficulties they face in the creative process. Costello remarks that he sometimes writes notes that he can't sing, only to be disappoint himself when he gets into the studio. Waits commiserates:

Anything that has to travel all the way down from your cerebellum to your fingertips, there's a lot of things that can happen on the journey. Sometimes I'll listen to records, my own stuff, and I think god, the original idea for this was so much better than the mutation that we arrived at. What I'm trying to do now is get what comes and keep it alive. It's like carrying water in your hands. I want to keep it all, and sometimes by the time you get to the studio you have nothing.

This is something I notice all the time when I'm teaching. I'll have an idea for class somewhere: walking home, riding the exercise bike, reading something. My brain dives into the process of making the idea real: telling a story, writing code, explaining an idea in relation to things we've done in class before. Then comes deployment. We get into the classroom and... it feels flat. On rare occasions the new ideas bombs, but most often it just seems not quite right. It doesn't feel like what I had in my mind when I first had the idea, and I'm not sure how we ended up feeling the way we feel in class. The idea was so perfect.

Teaching ideas are abstraction. Teaching is concrete. It involves other humans. Their learning is what's important, and sometimes the idea doesn't make the connection intended by the teacher. The classroom is where reality sets in.

There is good news. Sometimes a disappointing or failed idea can be salvaged by analyzing the experience and redesigning the session. But most of the time it never feels as perfect as it did in my head at the moment of conception. Part of the art of becoming a teaching is making friends with this fact and moving forward.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

February 18, 2020 4:00 PM

Programming Feels Like Home

I saw Robin Sloan's An App Can Be a Home-Cooked Meal floating around Twitter a few days back. It really is quite good; give it a read if you haven't already. This passage captures a lot of the essay's spirit in only a few words:

The exhortation "learn to code!" has its foundations in market value. "Learn to code" is suggested as a way up, a way out. "Learn to code" offers economic leverage, a squirt of power. "Learn to code" goes on your resume.
But let's substitute a different phrase: "learn to cook." People don't only learn to cook so they can become chefs. Some do! But far more people learn to cook so they can eat better, or more affordably, or in a specific way. Or because they want to carry on a tradition. Sometimes they learn just because they're bored! Or even because -- get this -- they love spending time with the person who's teaching them.

Sloan expresses better than I ever have an idea that I blog about every so often. Why should people learn to program? Certainly it offers a path to economic gain, and that's why a lot of students study computer science in college, whether as a major, a minor, or a high-leverage class or two. There is nothing wrong with that. It is for many a way up, a way out.

But for some of us, there is more than money in programming. It gives you a certain power over the data and tools you use. I write here occasionally about how a small script or a relatively small program makes my life so much easier, and I feel bad for colleagues who are stuck doing drudge work that I jump past. Occasionally I'll try to share my code, to lighten someone else's burden, but most of the time there is such a mismatch between the worlds we live in that they are happier to keep plugging along. I can't say that I blame them. Still, if only they could program and used tools that enabled them to improve their work environments...

But... There is more still. From the early days of this blog, I've been open with you all:

Here's the thing. I like to write code.

One of the things that students like about my classes is that I love what I do, and they are welcome to join me on the journey. Just today a student in my Programming Languages drifted back to my office with me after class , where we ended up talking for half an hour and sketching code on a whiteboard as we deconstructed a vocabulary choice he made on our latest homework assignment. I could sense this student's own love of programming, and it raised my spirits. It makes me more excited for the rest of the semester.

I've had people come up to me at conferences to say that the reason they read my blog is because they like to see someone enjoying programming as much as they do. many of them share links with their students as if to say, "See, we are not alone." I look forward to days when I will be able to write in this vein more often.

Sloan reminds us that programming can be -- is -- more than a line on a resume. It is something that everyone can do, and want to do, for a lot of different reasons. It would be great if programming "were marbled deeply into domesticity and comfort, nerdiness and curiosity, health and love" in the way that cooking is. That is what makes Computing for All really worth doing.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Software Development, Teaching and Learning

January 22, 2020 3:54 PM

The Roots of TDD -- from 1957

In 1957, Dan McCracken published Digital Computer Programming, perhaps the first book on the new art of programming. His book shows that the roots of extreme programming run deep. In this passage, McCracken encourages both the writing of tests before the writing of code and the involvement of the customer in the software development process:

The first attack on the checkout problem may be made before coding is begun. In order to fully ascertain the accuracy of the answers, it is necessary to have a hand-calculated check case with which to compare the answers which will later be calculated by the machine. This means that stored program machines are never used for a true one-shot problem. There must always be an element of iteration to make it pay. The hand calculations can be done at any point during programming. Frequently, however, computers are operated by computing experts to prepare the problems as a service for engineers or scientists. In these cases it is highly desirable that the "customer" prepare the check case, largely because logical errors and misunderstandings between the programmer and customer may be pointed out by such procedure. If the customer is to prepare the test solution is best for him to start well in advance of actual checkout, since for any sizable problem it will take several days or weeks to calculate the test.

I don't have a copy of this book, but I've read a couple of other early books by McCracken, including one of his Fortran books for engineers and scientists. He was a good writer and teacher.

I had the great fortune to meet Dan at an NSF workshop in Clemson, South Carolina, back in the mid-1990s. We spent many hours in the evening talking shop and watching basketball on TV. (Dan was cheering his New York Knicks on in the NBA finals, and he was happy to learn that I had been a Knicks and Walt Frazier fan in the 1970s.) He was a pioneer of programming and programming education who was willing to share his experience with a young CS prof who was trying to figure out how to teach. We kept in touch by email thereafter. It was honor to call him a friend.

You can find the above quotation in A History of Test-Driven Development (TDD), as Told in Quotes, by Rob Myers. That post includes several good quotes that Myers had to cut from his upcoming book on TDD. "Of course. How else could you program?"

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

January 10, 2020 2:25 PM


I recently read an interview with documentary filmmaker Errol Morris, who has unorthodox opinions about documentaries and how to make them. In particular, he prefers to build his films out of extended interviews with a single subject. These interviews give him all the source material he needs, because they aren't about questions and answers. They are about stories:

First of all, I think all questions are more or less rhetorical questions. No one wants their questions answered. They just want to state their question. And, in answering the question, the person never wants to answer the question. They just want to talk.

Morris isn't asking questions; he is stating them. His subjects are not answering questions; they are simply talking.

(Think about this the next time your listening to an interview with a politician or candidate for office...)

At first, I was attracted to the sentiment in this paragraph. Then I became disillusioned with what I took to be its cynicism. Now, though, after a week or so, I am again enamored with its insight. How many of the questions I ask of software clients and professional colleagues are really statements of a position? How many of their answers are disconnected from the essential element of my questions? Even when these responses are disconnected, they communicate a lot to me, if only I listen. My clients and colleagues are often telling me exactly what they want me to know. This dynamic is present surprisingly often when I work with students at the university, too. I need to listen carefully when students don't seem to be answering my question. Sometimes it's because they have misinterpreted the question, and I need to ask differently. Sometimes it's because they are telling me what they want me to know, irrespective of the question.

And when my questions aren't really questions, but statements or some other speech act... well, I know I have some work to do.

In case you find Morris's view on interviews cynical and would prefer to ponder the new year with greater hope, I'll leave you with a more ambiguous quote about questions:

There are years that ask questions, and years that answer.

That's from Their Eyes Were Watching God, by Zora Neale Hurston. In hindsight, it may be true or false for any given year. As a way to frame the coming months, though, it may be useful.

I hope that 2020 brings you the answers you seek, or the questions.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

January 06, 2020 3:13 PM

A Writing Game

I recently started reading posts in the archives of Jason Zweig's blog. He writes about finance for a living but blogs more widely, including quite a bit about writing itself. An article called On Writing Better: Sharpening Your Tools challenges writers to look at each word they write as "an alien object":

As the great Viennese journalist Karl Kraus wrote, "The closer one looks at a word, the farther away it moves." Your goal should be to treat every word you write as an alien object: You should be able to look at it and say, What is that doing here? Why did I use that word instead of a better one? What am I trying to say here? How can I get to where I'm going if I use such stale and lifeless words?

My mind immediately turned this into a writing game, an exercise that puts the idea into practice. Take any piece of writing.

  1. Choose a random word in the document.
  2. Change the word -- or delete it! -- in a way that improves the text.
  3. Go to 1.

Play the game for a fixed number of rounds or for a fixed period of time. A devilish alternative is to play until you get so frustrated with your writing that you can't continue. You could then judge your maturity as a writer by how long you can play in good spirits.

We could even automate the mechanics of the game by writing a program that chooses a random word in a document for us. Every time we save the document after a change, it jumps to a new word.

As with most first ideas, this one can probablyb be improved. Perhaps we should bias word selection toward words whose replacement or deletion are most likely to improve our writing. Changing "the" or "to" doesn't offer the same payoff as changing a lazy verb or deleting an abstract adverb. Or does it? I have a lot of room to improve as a writer; maybe fixing some "the"s and "to"s is exactly what I need to do. The Three Bears pattern suggests that we might learn something by tackling the extreme form of the challenge and seeing where it leads us.

Changing or deleting a single word can improve a piece of text, but there is bigger payoff available, if we consider the selected word in context. The best way to eliminate many vague nouns is to turn them back into verbs, where they act with vigor. To do that, we will have to change the structure of the sentence, and maybe the surrounding sentences. That forces us to think even more deeply about the text than changing a lone word. It also creates more words for us to fix in following rounds!

I like programming challenges of this sort. A writing challenge that constrains me in arbitrary ways might be just what I need to take time more often to improved my work. It might help me identify and break some bad habits along the way. Maybe I'll give this a try and report back. If you try it, please let me know the results!

And no, I did not play the game with this post. It can surely be improved.

Postscript. After drafting this post, I came across another article by Zweig that proposes just such a challenge for the narrower case of abstract adverbs:

The only way to see if a word is indispensable is to eliminate it and see whether you miss it. Try this exercise yourself:
  • Take any sentence containing "actually" or "literally" or any other abstract adverb, written by anyone ever.
  • Delete that adverb.
  • See if the sentence loses one iota of force or meaning.
  • I'd be amazed if it does (if so, please let me know).

We can specialize the writing game to focus on adverbs, another part of speech, or almost any writing weakness. The possibilities...

Posted by Eugene Wallingford | Permalink | Categories: General, Patterns, Teaching and Learning

December 20, 2019 1:45 PM

More Adventures in Constrained Programming: Elo Predictions

I like tennis. The Tennis Abstract blog helps me keep up with the game and indulge my love of sports stats at the same time. An entry earlier this month gave a gentle introduction to Elo ratings as they are used for professional tennis:

One of the main purposes of any rating system is to predict the outcome of matches--something that Elo does better than most others, including the ATP and WTA rankings. The only input necessary to make a prediction is the difference between two players' ratings, which you can then plug into the following formula:

1 - (1 / (1 + (10 ^ (difference / 400))))

This formula always makes me smile. The first computer program I ever wrote because I really wanted to was a program to compute Elo ratings for my high school chess club. Over the years I've come back to Elo ratings occasionally whenever I had an itch to dabble in a new language or even an old favorite. It's like a personal kata of variable scope.

I read the Tennis Abstract piece this week as my students were finishing up their compilers for the semester and as I was beginning to think of break. Playful me wondered how I might implement the prediction formula in my students' source language. It is a simple functional language with only two data types, integers and booleans; it has no loops, no local variables, no assignments statements, and no sequences. In another old post, I referred to this sort of language as akin to an integer assembly language. And, heaven help me, I love to program in integer assembly language.

To compute even this simple formula in Klein, I need to think in terms of fractions. The only division operator performs integer division, so 1/x for any x gives 0. I also need to think carefully about how to implement the exponentiation 10 ^ (difference / 400). The difference between two players' ratings is usually less than 400 and, in any case, almost never divisible by 400. So My program will have to take an arbitrary root of 10.

Which root? Well, I can use our gcd() function (implemented using Euclid's algorithm, of course) to reduce diff/400 to its lowest terms, n/d, and then compute the dth root of 10^n. Now, how to take the dth root of an integer for an arbitrary integer d?

Fortunately, my students and I have written code like this in various integer assembly languages over the years. For instance, we have a SQRT function that uses binary search to hone in on the integer closest to the square of a given integer. Even better, one semester a student implemented a square root program that uses Newton's method:

   xn+1 = xn - f(xn)/f'(xn)

That's just what I need! I can create a more general version of the function that uses Newton's method to compute an arbitrary root of an arbitrary base. Rather than work with floating-point numbers, I will implement the function to take its guess as a fraction, represented as two integers: a numerator and a denominator.

This may seem like a lot of work, but that's what working in such a simple programming language is like. If I want my students' compilers to produce assembly language that predicts the result of a professional tennis match, I have to do the work.

This morning, I read a review of Francis Su's new popular math book, Mathematics for Human Flourishing. It reminds us that math isn't about rules and formulas:

Real math is a quest driven by curiosity and wonder. It requires creativity, aesthetic sensibilities, a penchant for mystery, and courage in the face of the unknown.

Writing my Elo rating program in Klein doesn't involve much mystery, and it requires no courage at all. It does, however, require some creativity to program under the severe constraints of a very simple language. And it's very much true that my little programming diversion is driven by curiosity and wonder. It's fun to explore ideas in a small space uses limited tools. What will I find along the way? I'll surely make design choices that reflect my personal aesthetic sensibilities as well as the pragmatic sensibilities of a virtual machine that know only integers and booleans.

As I've said before, I love to program.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 12, 2019 3:20 PM

A Semester's Worth of Technical Debt

I've been thinking a lot about technical debt this week. My student teams are in Week 13 of their compiler project and getting ready to submit their final systems. They've been living with their code long enough now to appreciate Ward Cunningham's original idea of technical debt: the distance between their understanding and the understanding embodied in their systems.

... it was important to me that we accumulate the learnings we did about the application over time by modifying the program to look as if we had known what we were doing all along and to look as if it had been easy to do in Smalltalk.

Actually, I think they are experiencing two gulfs: one relates to their understanding of the domain, compilers, and the other to their understanding of how to build software. Obviously, they are just learning about compilers and how to build one, so their content knowledge has grown rapidly while they've been programming. But they are also novice software engineers. They are really just learning how to build a big software system of any kind. Their knowledge of project management, communication, and their tools has also grown rapidly in parallel with building their system.

They have learned a lot about both content and process this semester. Several of them wish they had time to refactor -- to pay back the debt they accumulated honestly along the way -- but university courses have to end. Perhaps one or two of them will do what one or two students in most past semesters have done: put some of their own time into their compilers after the course ends, to see if they can modify the program to look as if they had known what they were doing all along, and to look as if it had been easy to do in Java or Python. There's a lot of satisfaction to be found at the end of that path, if they have the time and curiosity to take it.

One team leader tried to bridge the gulf in real time over the last couple of weeks: He was so unhappy with the gap between his team's code and their understanding that he did a complete rewrite of the first five stages of their compiler. This team learned what every team learns about rewrites and large-scale refactoring: they spend time that could otherwise have been spent on new development. In a time-boxed course, this doesn't always work well. That said, though, they will likely end up with a solid compiler -- as well as a lot of new knowledge about how to build software.

Being a prof is fun in many ways. One is getting to watch students learn how to build something while they are building it, and coming out on the other side with new code and new understanding.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

December 04, 2019 2:42 PM

Make Your Code Say What You Say When You Describe It

Brian Marick recently retweeted this old tweet from Ron Jeffries:

You: Explain this code to me, please.
They: blah blah blah.
You: Show me where the code says that.
They: <silence>
You: Let's make it say that.

I find this strategy quite helpful when writing my own code. If I can't explain any bit of code to myself clearly and succinctly, then I can take a step back and work on fixing my understanding before trying to fix the code. Once I understand, I'm a big fan of creating functions or methods whose names convey their meaning.

This is also a really handy strategy for me in my teaching. As a prof, I spend a fair amount of time explaining code I've written to students. The act of explaining a piece of code, whether written or spoken, often points me toward ways I can make the program better. If I find myself explaining the same piece of code to several students over time, I know the code can probably be better. So I try to fix it.

I also use a gentler variation of Jeffries' approach when working directly with students and their code. I try whenever I can to help my students learn how to write better programs. It can be tempting to start lecturing them on ways that their program could be better, but unsolicited advice of this sort rarely finds a happy place to land in their memory. Asking questions can be more effective, because questions can lead to a conversation in which students figure some things out on their own. Asking general questions usually isn't helpful, though, because students may not have enough experience to connect the general idea to the details of their program.

So: I find it helpful to ask a student to explain their code to me. Often they'll give me a beautiful answer, short and clear, that stands in obvious contrast to the code we are looking at out. This discrepancy leads to a natural follow-up question: How might we change the code so that it says that? The student can take the lead in improving their own programs, guided by me with bits of experience they haven't had yet.

Of course, sometimes the student's answer is complex or rambles off into silence. That's a cue to both of us that they don't really understand yet what they are trying to do. We can take a step back and help them fix their understanding -- of the problem or of the programming technique -- before trying to fix the code itself.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

December 02, 2019 11:41 AM

XP as a Long-Term Learning Strategy

I recently read Anne-Laure Le Cunff's Interleaving: Rethink The Way You Learn. Le Cunff explains why interleaving -- "the process of mixing the practice of several related skills together" -- is more effective for long-term learning than blocked practice, in which students practice a single skill until they learn it and then move on to the next skill. Interleaving forces the brain to retrieve different problem-solving strategies more frequently and under different circumstances, which reinforces neural connections and improves learning.

To illustrate the distinction between interleaving and blocked practice, Le Cunff uses this image:

interleaving versus blocked practice

When I saw that diagram, I thought immediately of Extreme Programming. In particular, I thought of a diagram I once saw that distinguished XP from more traditional ways of building software in terms of how quickly it moved through the steps of the development life cycle. That image looked something like this:

XP interleaves the stages of the software development life cycle

If design is good, why not do it all the time? If testing is good, why not do it all the time, too?

I don't think that the similarity between these two images is an accident. It reflects one of XP's most important, if sometimes underappreciated, benefits: By interleaving short spurts of analysis, design, implementation, and testing, programmers strengthen their understanding of both the problem and the evolving code base. They develop stronger long-term memory associations with all phases of the project. Improved learning enables them to perform even more effectively deeper in the project, when these associations are more firmly in place.

Le Cunff offers a caveat to interleaved learning that also applies to XP: "Because the way it works benefits mostly our long-term retention, interleaving doesn't have the best immediate results." The benefits of XP, including more effective learning, accrue to teams that persist. Teams new to XP are sometimes frustrated by the small steps and seemingly narrow focus of their decisions. With a bit more experience, they become comfortable with the rhythm of development and see that their code base is more supple. They also begin to benefit from the more effective learning that interleaved practice provides.


Image 1: This image comes from Le Cunff's article, linked above. It is by Anne-Laure Le Cunff, copyright Ness Labs 2019, and reproduced here with permission.

Image 2: I don't remember where I saw the image I hold in my memory, and a quick search through Extreme Programming Explained and Google's archives did not turn up anything like it. So I made my own. It is licensed CC BY-SA 4.0.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

November 10, 2019 11:06 AM

Three of the Hundred Falsehoods CS Students Believe

Jan Schauma recently posted a list of one hundred Falsehoods CS Students (Still) Believe Upon Graduating. There is much good fun here, especially for a prof who tries to help CS students get ready for the world, and a fair amount of truth, too. I will limit my brief comments to three items that have been on my mind recently even before reading this list.

18. 'Email' and 'Gmail' are synonymous.

CS grads are users, too, and their use of Gmail, and systems modeled after it, contributes to the truths of modern email: top posting all the time, with never a thought of trimming anything. Two-line messages sitting atop icebergs of text which will never be read again, only stored in the seemingly infinite space given us for free.

Of course, some of our grads end up in corporate and IT, managing email as merely one tool in a suite of lowest-common-denominator tools for corporate communication. The idea of email as a stream of text that can, for the most part, be read as such, is gone -- let alone the idea that a mail stream can be processed by programs such as procmail to great benefit.

I realize that most users don't ask for anything more than a simple Gmail filter to manage their mail experience, but I really wish it were easier for more users with programming skills to put those skills to good use. Alas, that does not fit into the corporate IT model, and not even the CS grads running many of these IT operations realize or care what is possible.

38. Employers care about which courses they took.

It's the time of year when students register for spring semester courses, so I've been meeting with a lot of students. (Twice as many as usual, covering for a colleague on sabbatical.) It's interesting to encounter students on both ends of the continuum between not caring at all what courses they take and caring a bit too much. The former are so incurious I wonder how they fell into the major at all. The latter are often more curious but sometimes are captive to the idea that they must, must, must take a specific course, even if it meets at a time they can't attend or is full by the time they register.

I do my best to help them get into these courses, either this spring or in a late semester, but I also try to do a little teaching along the way. Students will learn useful and important things in just about every course they take, if they want to, and taking any particular course does not have to be either the beginning or the end of their learning of that topic. And if the reason they think they must take a particular course is because future employers will care, they are going to be surprised. Most of the employers who interview our students are looking for well-rounded CS grads who have a solid foundation in the discipline and who can learn new things as needed.

90. Two people with a CS degree will have a very similar background and shared experience/knowledge.

This falsehood operates in a similar space to #38, but at the global level I reached at the end of my previous paragraph. Even students who take most of the same courses together will usually end their four years in the program with very different knowledge and experiences. Students connect with different things in each course, and these idiosyncratic memories build on one another in subsequent courses. They participate in different extracurricular activities and work different part-time jobs, both of shape and augment what they learn in class.

In the course of advising students over two, three, or four years, I try to help them see that their studies and other experiences are helping them to become interesting people who know more than they realize and who are individuals, different in some respects from all their classmates. They will be able to present themselves to future employers in ways that distinguish them from everyone else. That's often the key to getting the job they desire now, or perhaps one they didn't even realize they were preparing for while exploring new ideas and building their skillsets.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

October 27, 2019 10:23 AM

Making Something That Is Part Of Who You Are

The narrator in Rachel Cusk's "Transit" relates a story told to her by Pavel, the Polish builder who is helping to renovate her flat. Pavel left Poland for London to make money after falling out with his father, a builder for whom he worked. The event that prompted his departure was a reaction to a reaction. Pavel had designed and built a home for his family. After finishing, he showed it to his father. His father didn't like it, and said so. Pavel chose to leave at that moment.

'All my life,' he said, 'he criticise. He criticise my work, my idea, he say he don't like the way I talk -- even he criticise my wife and my children. But when he criticise my house' -- Pavel pursed his lips in a smile -- 'then I think, okay, is enough.'

I generally try to separate myself from the code and prose I write. Such distance is good for the soul, which does not need to be buffeted by criticism, whether external or internal, of the things I've created. It is also good for the work itself, which is free to be changed without being anchored to my identity.

Fortunately, I came out of home and school with a decent sense that I could be proud of the things I create without conflating the work with who I am. Participating in writers' workshops at PLoP conferences early in my career taught me some new tools for hearing feedback objectively and focusing on the work. Those same tools help me to give feedback better. I use them in an effort to help my students develop as people, writers and programmers independent of the code and prose they write.

Sometimes, though, we make things that are expressions of ourselves. They carry part of us in their words, in what they say to the world and how they say it. Pavel's house is such a creation. He made everything: the floors, the doors, and the roof; even the beds his children slept in. His father had criticized his work, his ideas, his family before. But criticizing the house he had dreamed and built -- that was enough. Cusk doesn't give the reader a sense that this criticism was a last straw; it was, in a very real way, the only straw that mattered.

I think there are people in this world who would like just once in their lives to make something that is so much a part of who they are that they feel about it as Pavel does his house. They wish to do so despite, or perhaps because of, the sharp line it would draw through the center of life.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

August 30, 2019 4:26 PM

Unknown Knowns and Explanation-Based Learning

Like me, you probably see references to this classic quote from Donald Rumsfeld all the time:

There are known knowns; there are things we know we know. We also know there are known unknowns; that is to say, we know there are some things we do not know. But there are also unknown unknowns -- the ones we don't know we don't know.

I recently ran across it again in an old Epsilon Theory post that uses it to frame the difference between decision making under risk (the known unknowns) and decision-making under uncertainty (the unknown unknowns). It's a good read.

Seeing the passage again for the umpteenth time, it occurred to me that no one ever seems to talk about the fourth quadrant in that grid: the unknown knowns. A quick web search turns up a few articles such as this one, which consider unknown knowns from the perspective of others in a community: maybe there are other people who know something that you do not. But my curiosity was focused on the first-person perspective that Rumsfeld was implying. As a knower, what does it mean for something to be an unknown known?

My first thought was that this combination might not be all that useful in the real world, such as the investing context that Ben Hunt writes about in Epsilon Theory. Perhaps it doesn't make any sense to think about things you don't know that you know.

As a student of AI, though, I suddenly made an odd connection ... to explanation-based learning. As I described in a blog post twelve years ago:

Back when I taught Artificial Intelligence every year, I used to relate a story from Russell and Norvig when talking about the role knowledge plays in how an agent can learn. Here is the quote that was my inspiration, from Pages 687-688 of their 2nd edition:

Sometimes one leaps to general conclusions after only one observation. Gary Larson once drew a cartoon in which a bespectacled caveman, Zog, is roasting his lizard on the end of a pointed stick. He is watched by an amazed crowd of his less intellectual contemporaries, who have been using their bare hands to hold their victuals over the fire. This enlightening experience is enough to convince the watchers of a general principle of painless cooking.

I continued to use this story long after I had moved on from this textbook, because it is a wonderful example of explanation-based learning.

In a mathematical sense, explanation-based learning isn't learning at all. The new fact that the program learns follows directly from other facts and inference rules already in its database. In EBL, the program constructs a proof of a new fact and adds the fact to its database, so that it is ready-at-hand the next time it needs it. The program has compiled a new fact, but in principle it doesn't know anything more than it did before, because it could always have deduced that fact from things it already knows.

As I read the Epsilon Theory article, it struck me that EBL helps a learner to surface unknown knowns by using specific experiences as triggers to combine knowledge it already into a piece of knowledge that is usable immediately without having to repeat the (perhaps costly) chain of inference ever again. Deducing deep truths every time you need them can indeed be quite costly, as anyone who has ever looked at the complexity of search in logical inference systems can tell you.

When I begin to think about unknown knowns in this way, perhaps it does make sense in some real-world scenarios to think about things you don't know you know. If I can figure it all out, maybe I can finally make my fortune in the stock market.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Teaching and Learning

August 25, 2019 10:00 AM

Learn the Basics, Struggle a Bit, Then Ask Questions

Earlier this week, there was a meme on Twitter where people gave one-line advice to young students as they stepped onto a college campus as first-years, to help them enjoy and benefit from their college years. I didn't have anything clever or new to say, so I didn't join in, but something I read this morning triggered a bit of old wisdom that I wish more students would try to live out. In tweet-size form, it might be: "Learn the basics, struggle a bit, then ask questions." Here's the blog-size version.

In Tyler Cowen's conversation with Google economist Hal Varian, Cowen asks about a piece of advice Varian had once given to graduate students: "Don't look at the literature too soon." Is that still good advice, and why? Yes, Varian replied...

VARIAN: Because if you look at the literature, you'll see this completely worked-out problem, and you'll be captured by that person's viewpoint. Whereas, if you flounder around a little bit yourself, who knows? You might come across a completely different phenomenon. Now, you do have to look at the literature. I want to emphasize that. But it's a good idea to wrestle with a problem a little bit on your own before you adopt the standard viewpoint.

Grad students are often trying to create new knowledge, so it's best for them not to lock themselves into existing ways of thinking too soon. Thus: Don't look at the literature too soon.

I work mostly with undergrads, who study in a different context than grad students. But I think that the core of Varian's advice works well for undergrads, too: Start by learning a few basic ideas in class. Then try to solve problems. Then ask questions.

Undergrads are usually trying to master foundational material, not create new knowledge, so it's tempting to want to jump straight to answers. But it's still to valuable approach the task of learning as a process of building one's own understanding of problems before seeking answers. Banging on a bunch of problems helps us to build instincts about what the important issues and to explore the fuzzy perimeter between the basics and the open questions that will vex us after we master them. That happens best when we don't see a solution right away, when what we learned in class doesn't seem to point us directly to a solution and we have to find our own way.

But do ask questions! A common theme among students who struggle in my courses is the belief they just have to work harder or longer on a problem. Too many times I've had a student tell me "I spent an hour on each of the five homework problems." Really? My goal is for each problem to take 15 minutes or less. After half an hour, or maybe a second attempt the next day, maybe you are missing something small but important. Ask a question; maybe a little nudge can put you on the right track. Sometimes, your question will help me realize that it's the problem which is flawed and needs a tweak!

Back at the beginning of the process, too strong a belief in the ability to figure things out on one's own creates a different sort of breakdown in the learning process: It can be tempting to skip over what you read in your textbook and what you learn in class, and start trying to solving problems. "It's basic material, right? I'll figure it out." You might, but that's taking the idea to an unhealthy level. There's a difference between seeking answers too soon and trying to solve problems without the basic tools you need. Trust your profs a little bit... In class, they are trying to give you the basic tools you need to solve interesting problems.

There's nothing new here. But let's be honest; there isn't much new to be found in ways to learn. Even in the digital age, the basic tenets remain true. That's why I extol curiosity and persistence and why I'd rather be Mr. Miyagi than an answer machine. Learning will be uncomfortable. The trick is to find a way to balance the curiosity with the discomfort, the not-knowing with the receiving of answers and moving on. I wish I had great advice for how to find that balance, but I think people ultimately have to do that for themselves. We benefit by being part of a community of learners, but we each learn in our own ways and on our own time.

Actually, writing up this post has led me to a goal for myself as a teacher this year, and which may be good advice for my fellow teachers: Be more explicit about my expectations of students. This is true both at the micro-level of, say, how much time to spend on homework problems before seeking help, and at the macro-level of how to approach learning. If I want students to do something, I should at least remove the barriers between what they are thinking they should do and what I would like for them to do.

So there's some advice for students and some advice for teachers. Let's enjoy the new year and learn together.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

August 02, 2019 2:48 PM

Programming is an Infinite Construction Kit

As so often, Marvin Minsky loved to tell us about the beauty of programming. Kids love to play with construction sets like Legos, TinkerToys, and Erector sets. Programming provides an infinite construction kit: you never run out of parts!

In the linked essay, which was published as a preface to a 1986 book about Logo, Minsky tells several stories. One of the stories relates that once, as a small child, he built a large tower out of TinkerToys. The grownups who saw it were "terribly impressed". He inferred from their reaction that:

some adults just can't understand how you can build whatever you want, so long as you don't run out of sticks and spools.

Kids get it, though. Why do so many of us grow out of this simple understanding as we get older? Whatever its cause, this gap between children's imaginations and the imaginations of adults around them creates a new sort of problem when we give the children a programming language such as Logo or Scratch. Many kids take to these languages just as they do to Legos and TinkerToys: they're off to the races making things, limited only by their expansive imaginations. The memory on today's computers is so large that children never run out of raw material for writing programs. But adults often don't possess the vocabulary for talking with the children about their creations!

... many adults just don't have words to talk about such things -- and maybe, no procedures in their heads to help them think of them. They just do not know what to think when little kids converse about "representations" and "simulations" and "recursive procedures". Be tolerant. Adults have enough problems of their own.

Minsky thinks there are a few key ideas that everyone should know about computation. He highlights two:

Computer programs are societies. Making a big computer program is putting together little programs.

Any computer can be programmed to do anything that any other computer can do--or that any other kind of "society of processes" can do.

He explains the second using ideas pioneered by Alan Turing and long championed in the popular sphere by Douglas Hofstadter. Check out this blog post, which reflects on a talk Hofstadter gave at my university celebrating the Turing centennial.

The inability of even educated adults to appreciate computing is a symptom of a more general problem. As Minsky says toward the end of his essay, People who don't appreciate how simple things can grow into entire worlds are missing something important. If you don't understand how simple things can grow into complex systems, it's hard to understand much at all about modern science, including how quantum mechanics accounts for what we see in the world and even how evolution works.

You can usually do well by reading Minsky; this essay is a fine example of that. It comes linked to an afterword written by Alan Kay, another computer scientist with a lot to say about both the beauty of computing and its essential role in a modern understanding of the world. Check both out.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

June 20, 2019 3:51 PM

Implementing a "Read Lines" Operator in Joy

I wasn't getting any work done today on my to-do list, so I decided to write some code.

One of my learning exercises to open the Summer of Joy is to solve the term frequency problem from Crista Lopes's Exercises in Programming Style. Joy is a little like Scheme: it has a lot of cool operations, especially higher-order operators, but it doesn't have much in the way of practical level tools for basic tasks like I/O. To compute term frequencies on an arbitrary file, I need to read the file onto Joy's stack.

I played around with Joy's low-level I/O operators for a while and built a new operator called readfile, which expects the pathname for an input file on top of the stack:

    DEFINE readfile ==
        (* 1 *)  [] swap "r" fopen
        (* 2 *)  [feof not] [fgets swap swonsd] while
        (* 3 *)  fclose.

The first line leaves an empty list and an input stream object on the stack. Line 2 reads lines from the file and conses them onto the list until it reaches EOF, leaving a list of lines under the input stream object on the stack. The last line closes the stream and pops it from the stack.

This may not seem like a big deal, but I was beaming when I got it working. First of all, this is my first while in Joy, which requires two quoted programs. Second, and more meaningful to me, the loop body not only works in terms of the dip idiom I mentioned in my previous post, it even uses the higher-order swonsd operator to implement the idiom. This must be how I felt the first time I mapped an anonymous lambda over a list in Scheme.

readfile leaves a list of lines on the stack. Unfortunately, the list is in reverse order: the last line of the file is the front of the list. Besides, given that Joy is a stack-based language, I think I'd like to have the lines on the stack itself. So I noodled around some more and implemented the operator pushlist:

    DEFINE pushlist ==
        (* 1 *)  [ null not ] [ uncons ] while
        (* 2 *)  pop.

Look at me... I get one loop working, so I write another. The loop on Line 1 iterates over a list, repeatedly taking (head . tail) and pushing head and tail onto the stack in that order. Line 2 pops the empty list after the loop terminates. The result is a stack with the lines from the file in order, first line on top:

    line-n ... line-3 line-2 line-1

Put readfile and pushlist together:

    DEFINE fileToStack == readfile pushlist.
and you get fileToStack, something like Python's readlines() function, but in the spirit of Joy: the file's lines are on the stack ready to be processed.

I'll admit that I'm pleased with myself, but I suspect that this code can be improved. Joy has a lot of dandy higher-order operators. There is probably a better way to implement pushlist and maybe even readfile. I won't be surprised if there is a more idiomatic way to implement the two that makes the two operations plug together with less rework. And I may find that I don't want to leave bare lines of text on the stack after all and would prefer having a list of lines. Learning whether I can improve the code, and how, are tasks for another day.

My next job for solving the term frequency problem is to split the lines into individual words, canonicalize them, and filter out stop words. Right now, all I know is that I have two more functions in my toolbox, I learned a little Joy, and writing some code made my day better.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

June 11, 2019 3:04 PM

Summer of Joy

"Elementary" ideas are really hard & need to be revisited
& explored & re-revisited at all levels of mathematical
sophistication. Doing so actually moves math forward.

-- James Tanton

Three summers ago, I spent a couple of weeks re-familiarizing myself with the concatenative programming language Joy and trying to go a little deeper with the style. I even wrote a few blog entries, including a few quick lessons I learned in my first week with the language. Several of those lessons hold up, but please don't look at the code linked there; it is the raw code of a beginner who doesn't yet get the idioms of the style or the language. Then other duties at work and home pulled me away, and I never made the time to get back to my studies.

my Summer of Joy folder

I have dubbed this the Summer of Joy. I can't devote the entire summer to concatenative programming, but I'm making a conscious effort to spend a couple of days each week in real study and practice. After only one week, I have created enough forward momentum that I think about problems and solutions at random times of the day, such as while walking home or making dinner. I think that's a good sign.

An even better sign is that I'm starting to grok some of the idioms of the style. Joy is different from other concatenative languages like Forth and Factor, but it shares the mindset of using stack operators effectively to shape the data a program uses. I'm finally starting to think in terms of dip, an operator that enables a program to manipulate data just below the top of the stack. As a result, a lot of my code is getting smaller and beginning to look like idiomatic Joy. When I really master dip and begin to think in terms of other "dipping" operators, I'll know I'm really on my way.

One of my goals for the summer is to write a Joy compiler from scratch that I can use as a demonstration in my fall compiler course. Right now, though, I'm still in Joy user mode and am getting the itch for a different sort of language tool... As my Joy skills get better, I find myself refactoring short programs I've written in the past. How can I be sure that I'm not breaking the code? I need unit tests!

So my first bit of tool building is to implement a simple JoyUnit. As a tentative step in this direction, I created the simplest version of RackUnit's check-equal? function possible:

    DEFINE check-equal == [i] dip i =.
This operator takes two quoted programs (a test expression and an expected result), executes them, and compares the results. For example, this test exercises a square function:
    [ 2 square ] [ 4 ] check-equal.

This is, of course, only the beginning. Next I'll add a message to display when a test fails, so that I can tell at a glance which tests have failed. Eventually I'll want my JoyUnit to support tests as objects that can be organized into suites, so that their results can be tallied, inspected, and reported on. But for now, YAGNI. With even a few simple functions like this one, I am able to run tests and keep my code clean. That's a good feeling.

To top it all off, implementing JoyUnit will force me to practice writing Joy and push me to extend my understanding while growing the set of programming tools I have at my disposal. That's another good feeling, and one that might help me keep my momentum as a busy summer moves on.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

June 10, 2019 2:04 PM

Teach, That's My Advice

In Tyler Cowen's conversation with poet Elisa New, he asks closes with one of his standard questions:

COWEN: Last question. You meet an 18-year-old, and this person wants in some way to be a future version of you, Elisa New, and asks you for advice. What advice do you give them?
NEW: Teach.
COWEN: Teach.
NEW: Yes, teach the young, and yes, that's the advice. Because what teaching is, is learning to converse with others. It's to experience a topic as it grows richer and richer under the attentions of a community. That's what a classroom that really works is. It's a community that's ever rewarding.

New's justification for teaching has two parts. The first struck me as central to the task of becoming a poet, or a writer of any sort: learning to converse -- to express and exchange ideas -- with others. To converse is to use words and to experience their effects, both as speaker and listener. Over my years in the classroom, I've come to appreciate this benefit of teaching. It's made me a better teacher and, if not a better writer, at least a writer more aware of the different ways in which I can express my ideas.

New's second justification captures well the central value of teaching to an academic. To teach is to experience a topic as it grows richer under the attention of a community. What a wonderful phrase!

Some people think that teaching will steal time from their work as a literary scholar, historian, or scientist. But teaching helps us to see deeper into our discipline by urging us to examine it over and over from new vantage points. Every new semester and every new student creates a new conversation for me, and these conversations remind me that there is even more to a topic than I think -- more often than I ever thought they would before I became a professor. Just when I think I've mastered something, working with students seems most likely to help me see something new, in a way different than I might see something new through my own study.

This exposes one of the advantages of working in a graduate program or in an ongoing research lab: building a community that has some continuity over time. Teaching at an undergraduate institution means that not as many of my students will be able to work with me and one another on the same topic over time. Even so, follow-up courses and undergrad research projects do allow us to create overlapping communities with a lifespan longer than a single semester. It simply requires a different mindset than working in a big research lab.

So I heartily echo Professor New: teach, that's my advice.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

April 16, 2019 3:40 PM

The Importance of Giving Credit in Context

From James Propp's Prof. Engel's Marvelously Improbable Machines:

Chip-firing has been rediscovered independently in three different academic communities: mathematics, physics, and computer science. However, its original discovery by Engel is in the field of math education, and I strongly feel that Engel deserves credit for having been the first to slide chips around following these sorts of rules. This isn't just for Engel's sake as an individual; it's also for the sake of the kind of work that Engel did, blending his expertise in mathematics with his experience in the classroom. We often think of mathematical sophistication as something that leads practitioners to create concepts that can only be understood by experts, but at the highest reaches of mathematical research, there's a love of clarity that sees the pinnacle of sophistication as being the achievement of hard-won simplicity in settings where before there was only complexity.

First of all, Petri nets! I encountered Petri nets for the first time in a computer architecture course, probably as a master's student, and it immediately became my favorite thing about the course. I was never much into hardware and architecture, but Petri nets showed me a connection back to graph theory, which I loved. Later, I studied how to apply temporal logic to modeling hardware and found another way to appreciate my architecture courses.

But I really love the point that Propp makes in this paragraph and the section it opens. Most people think of research and teaching as being different sort of activities. But the kind of thinking one does in one often crosses over into the other. The sophistication that researchers have and use help us make sense of complex ideas and, at their best, help us communicate that understanding to a wide audience, not just to researchers at the same level of sophistication. The focus that teachers put on communicating challenging ideas to relative novices can encourage us to seek new formulations for a complex idea and ways to construct more complex ideas out of the new formulations. Sometimes, that can lead to an insight we can use in research.

In recent years, my research has benefited a couple times from trying to explain and demonstrate concatenative programming, as in Forth and Joy, to my undergraduate students. These haven't been breakthroughs of the sort that Engel made with his probability machines, but they've certainly help me grasp in new ways ideas I'd been struggling with.

Propp argues convincingly that it's important that we tell stories like Engel's and recognize that his breakthrough came as a result of his work in the classroom. This might encourage more researchers to engage as deeply with their teaching as with their research. Everyone will benefit.

Do you know any examples similar to the one Propp relates, but in the field of computer science? If so, I would love to hear about them. Drop me a line via email or Twitter.

Oh, and if you like Petri nets, probability, or fun stories about teaching, do read Propp's entire piece. It's good fun and quite informative.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 17, 2019 10:59 AM

Are We Curious Enough About Our Students?

I ran across an old interview with Douglas Crockford recently. When asked what traits were common to the weak programmers he'd seen over his career, Crockford said:

That's an easy one: lack of curiosity. They were so satisfied with the work that they were doing was good enough (without an understanding of what 'good' was) that they didn't push themselves.

I notice a lack of curiosity in many CS students, too. It's even easier for beginners than professional programmers to be satisfied with meeting the minimal requirements of a project -- "I got the right answers!" or, much worse, "It compiles!" -- and not realize that good code can be more. Part of our goal as teachers is to help students develop higher standards and more refined taste while they are in school.

There's another sense, though, in which holding students' lack of curiosity against them is a dangerous trap for professors. In moments of weakness, I occasionally look at my students and think, "Why doesn't this excite them more? Why don't they want to write code for fun?" I've come to realize over the years that our school system doesn't always do much to help students cultivate their curiosity. But with a little patience and a little conversation, I often find that my students are curious -- just not always about the things that intrigue me.

This shouldn't be a surprise. Even at the beginning of my career as a prof, I was a different sort of person than most of my students. Now that I'm a few years older, it's almost certain that I will not be in close connection with my students and what interests them most. Why would they necessarily care about the things I care about?

Bridging this gap takes time and energy. I have to work to build relationships both with individuals and with the group of students taking my course each semester. This work requires patience, which I've learned to appreciate more and more as I've taught. We don't always have the time we need in one semester, but that's okay. One of the advantages of teaching at a smaller school is time: I can get to know students over several semesters and multiple courses. We have a chance to build relationships that enrich the students' learning experience -- and my experience as a teacher.

Trying to connect with the curiosity of many different students creates logistical challenges when designing courses, examples, and assignments, of course. I'm often drawn back to Alan Kay's paradigm, Frank Oppenheimer's Exploratorium, which Kay discussed in his Turing Award lecture. The internet is, in many ways, a programmer's exploratorium, but it's so big, so disorganized, and of such varying levels of quality... Can we create collections of demos and problems that will contain something to connect with just about every student? Many of my posts on this blog, especially in the early years, grappled with this idea. (Here are two that specifically mention the Exploratorium: Problems Are The Thing and Mathematics, Problems, and Teaching.)

Sometimes I think the real question isn't: "Why aren't students more curious?" It is: "Are we instructors curious enough about our students?"

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

March 10, 2019 10:53 AM

Weekend Shorts

Andy Ko, in SIGCSE 2019 report:

I always have to warn my students before they attend SIGCSE that it's not a place for deep and nuanced discussions about learning, nor is it a place to get critical feedback about their ideas.
It is, however, a wonderful place to be immersed in the concerns of CS teachers and their perceptions of evidence.

I'm not sure I agree that one can't have deep, nuanced discussions about learning at SIGCSE, but it certainly is not a research conference. It is a great place to talk to and learn from people in the trenches teaching CS courses, with a strong emphasis on the early courses. I have picked up a lot of effective, creative, and inspiring ideas at SIGCSE over the years. Putting them onto sure scientific footing is part of my job when I get back.


Stephen Kell, in Some Were Meant for C (PDF), an Onward! 2017 essay:

Unless we can understand the real reasons why programmers continue to use C, we risk researchers continuing to solve a set of problems that is incomplete and/or irrelevant, while practitioners continue to use flawed tools.

For example,

... "faster safe languages" is seen as the Important Research Problem, not better integration.

... whereas Kell believes that C's superiority in the realm of integration is one of the main reasons that C remains a dominant, essential systems language.

Even with the freedom granted by tenure, academic culture tends to restrict what research gets done. One cause is a desire to publish in the best venues, which encourages work that is valued by certain communities. Another reason is that academic research tends to attract people who are interested in a certain kind of clean problem. CS isn't exactly "round, spherical chickens in a vacuum" territory, but... Language support for system integration, interop, and migration can seem like a grungier sort of work than most researchers envisioned when they went to grad school.

"Some Were Meant for C" is an elegant paper, just the sort of work, I imagine, that Richard Gabriel had when envisioned the essays track at Onward. Well worth a read.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

February 24, 2019 9:35 AM


In a conversation with Tyler Cowen, economist John Nye expresses disappointment with the nature of discourse in his discipline:

The thing I'm really frustrated by is that it doesn't matter whether people are writing from a socialist or a libertarian perspective. Too much of the discussion of political economy is normative. It's about "what should the ideal state be?"
I'm much more concerned with the questions of "what good states are possible?" And once good states are created that are possible, what good states are sustainable? And that, in my view, is a still understudied and very poorly understood issue.

For some reason, this made me think about software development. Programming styles, static and dynamic typing, software development methodologies, ... So much that is written about these topics tells us what's the right the thing to do. "Do this, and you will be able to reliably make good software."

I know I've been partisan on some of these issues over the course of my time as a programmer, and I still have my personal preferences. But these days especially I find myself more interested in "what good states are sustainable?". What has worked for teams? What conditions seem to make those practices work well or not so well? How do teams adapt to changes in the domain or the business or the team's make-up?

This isn't too say that we can't draw conclusions about forces and context. For example, small teams seem to make it easier to adapt to changing conditions; to make it work with bigger teams, we need to design systems that encourage attention and feedback. But it does mean that we can help others succeed without always telling them what they must do. We can help them find a groove that syncs with them and the conditions under which they work.

Standing back and surveying the big picture, it seems that a lot of good states are sustainable, so long as we pay attention and adapt to the world around us. And that should be good news to us all.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

January 29, 2019 1:46 PM

Dependencies and Customizable Books

Shriram Krishnamurthi, in Books as Software:

I have said that a book is a collection of components. I have concrete evidence that some of my users specifically excerpt sections that suit their purpose. ...

I forecast that one day, rich document formats like PDF will recognize this reality and permit precisely such specifications. Then, when a user selects a group of desired chapters to generate a thinner volume, the software will automatically evaluate constraints and include all dependencies. To enable this we will even need "program" analyses that help us find all the dependencies, using textual concordances as a starting point and the index as an auxiliary data structure.

I am one of the users Krishnamurthi speaks of, who has excerpted sections from his Programming Languages: Application and Interpretation to suit the purposes of my course. Though I've not written a book, I do post, use, adapt, and reuse detailed lecture notes for my courses, and as a result I have seen both sides of the divide he discusses. I occasionally change the order of topics in a course, or add a unit, or drop a unit. An unseen bit of work is to account for the dependencies among concepts, examples, problems, and code in the affected sections, but also in the new whole. My life is simpler than book writers who have to deal at least in part with rich document formats: I do everything in a small, old-style subset of HTML, which means I can use simple text-based tools for manipulating everything. But dependencies? Yeesh.

Maybe I need to write a big makefile for my course notes. Alas, that would not help me manage dependencies in the way I'd like, or in the way Krishnamurthi forecasts. As such, it would probably make things worse. I suppose that I could create the tool I need.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

January 08, 2019 2:10 PM

Sometimes, Copy and Paste Is the Right Thing To Do

Last week I blogged about writing code that is easy to delete, drawing on some great lines from an old 'programming is terrible' post. Here's another passage from @tef's post that's worth thinking more about:

Step 1: Copy-paste code

Building reusable code is something that's easier to do in hindsight with a couple of examples of use in the code base, than foresight of ones you might want later. On the plus side, you're probably re-using a lot of code already just by using the file-system, why worry that much? A little redundancy is healthy.

It's good to copy-paste code a couple of times, rather than making a library function, just to get a handle on how it will be used. Once you make something a shared API, you make it harder to change.

There's not a great one-liner in there, but these paragraphs point to a really important lesson, one that we programmers sometimes have a hard time learning. We are told so often "don't repeat yourself" that we come to think that all repetition is the same. It's not.

One use of repetition is in avoiding what @tef calls, in another 'programming is terrible' post, "preemptive guessing". Consider the creation of a new framework. Oftentimes, designing a framework upfront doesn't work very well because we don't know the domain's abstractions yet. One of the best ways to figure out what they are is to write several applications first, and let framework fall out the applications. While doing this, repetition is our friend: it's most useful to know what things don't change from one application to another. This repetition is a hint on how to build the framework we need. I learned this technique from Ralph Johnson.

I use and teach a similar technique for programming in smaller settings, too. When we see two bits of code that resemble one another, it often helps to increase the duplication in order to eliminate it. (I learned this idea from Kent Beck.) In this case, the goal of the duplication is to find useful abstractions. Sometimes, though, code duplication is really a hint to think differently about a problem. Factoring out a function or class -- finding a new abstraction -- may be incidental to the learning that takes place.

For me, this line from from the second programming-is-terrible post captures this idea perfectly:

... duplicate to find the right abstraction first, then deduplicate to implement it.

My spell checker objects to the word "deduplicate", but I'll allow it.

All of these ideas taken together are the reason that I think copy-and-paste gets an undeservedly bad name. Used properly, it is a valuable programming technique -- essential, really. I've long wanted to write a Big Ball of Mud-style paper about copy-and-paste patterns. There are plenty of good reasons why we write repetitive code and, as @tef says in the two posts I link to above, sometimes leaving duplication in your code is the right thing to do.

One final tribute to repetition for now. While researching this blog post, I ran across a blog entry of mine from October 2016. Apparently, I had just read @tef's Write code that is easy to delete... post and felt an undeniable urge to quote and comment on it. If you read that 2016 post, you'll see that my Writing code that is easy to delete post from last week duplicates it in spirit and, in a few cases, even the details. I swear that I read @tef's post again last week and wrote the new blog entry from scratch, with no memory of the 2016 events. I am perfectly happy with this second act. Sometimes, ideas circle through our brains again, changing us in imperceptible ways. As @tef says, a little redundancy is healthy.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

January 06, 2019 10:10 AM

Programming Never Feels Easier. You Just Solve Harder Problems.

Alex Honnold is a rock climber who was the first person to "free solo" Yosemite's El Capitan rock wall. In an interview for a magazine, he was asked what it takes to reach ever higher goals. One bit of advice was to "aim for joy, not euphoria". When you prepare to achieve a goal, it may not feel like a big surprise when you achieve it because you prepared to succeed. Don't expect to be overwhelmed by powerful emotions when you accomplish something new; doing so sets too high a standard and can demotivate you.

This paragraph, though, is the one that spoke to me:

Someone recently said to me about running: "It never feels easier--you just go faster." A lot of sports always feel terrible. Climbing is always like that. You always feel weak and like you suck, but you can do harder and harder things.

As a one-time marathoner, never fast but always training to run a PR in my next race, I know what Honnold means. However, I also feel something similar as a programmer. Writing software often seems like a slog that I'm not very good at. I'm forever looking up language features in order to get my code to work, and then I end up with programs that are bulky and fight me at every turn. I refactor and rewrite and... find myself back in the slog. I don't feel terrible all that often, but I am usually a little on edge.

Yet if I compare the programs I write today with ones I wrote 5 or 10 or 30 years ago, I can see that I'm doing more interesting work. This is the natural order. Once I know how to do one thing, I seek tougher problems to solve.

In the article, the passage quoted above is labeled "Feeling awful is normal." I wonder if programming feels more accessible to people who are comfortable with a steady, low-grade intellectual discomfort punctuated by occasional bouts of head banging. Honnold's observation might reassure beginning programmers who don't already know that feeling uneasy is a natural part of pushing yourself to do more interesting work.

All that said, even when I was training for my next marathon, I was always able to run for fun. There was nothing quite like an easy run at sunrise to boost my mood. Fortunately, I am still able to program that way, too. Every once in a while, I like to write code to solve some simple problem I run across on Twitter or in a blog entry somewhere. I find that these interludes recharge me before I battling the next big problem I decide to tackle. I hope that my students can still programming in this way as they advance on to bigger challenges.

Posted by Eugene Wallingford | Permalink | Categories: Running, Software Development, Teaching and Learning

January 02, 2019 2:22 PM

Writing Code that is Easy to Delete

Last week someone tweeted a link to Write code that is easy to delete, not easy to extend. It contains a lot of great advice on how to create codebases that are easy to maintain and easy to change, the latter being an essential feature of almost any code that is the former. I liked this article so much that I wanted to share some of its advice here. What follows are a few of the many one- and two-liners that serve as useful slogans for building maintainable software, with light commentary.

... repeat yourself to avoid creating dependencies, but don't repeat yourself to manage them.

This line from the first page of the paper hooked me. I'm not sure I had ever had this thought, at least not so succinctly, but it captures a bit of understanding that I think I had. Reading this, I knew I wanted to read the rest of the article.

Make a util directory and keep different utilities in different files. A single util file will always grow until it is too big and yet too hard to split apart. Using a single util file is unhygienic.

This isn't the sort of witticism that I quote in the rest of this post, but its solid advice that I've come to live by over the years. I have this pattern.

Boiler plate is a lot like copy-pasting, but you change some of the code in a different place each time, rather than the same bit over and over.

I really like the author's distinction between boilerplate and copy-and-paste. Copy-and-paste has valuable uses (heresy, I know; more later), whereas boilerplate sucks the joy out of almost every programmer's life.

You are writing more lines of code, but you are writing those lines of code in the easy-to-delete parts.

Another neat distinction. Even when we understand that lines of code are an expense as much as (or instead of) an investment, we know that sometimes we have write more code. Just do it in units that are easy to delete.

A lesson in separating concerns, from Python libraries:

requests is about popular http adventures, urllib3 is about giving you the tools to choose your own adventure.

Layers! I have had users of both of these libraries suggest that the other should not exist, but they serve different audiences. They meet different needs in a way that that more than makes up for the cost of the supposed duplication.

Building a pleasant to use API and building an extensible API are often at odds with each other.

There's nothing earth-shattering in this observation, but I like to highlight different kinds of trade-off whenever I can. Every important decision we make writing programs is a trade-off.

Good APIs are designed with empathy for the programmers who will use it, and layering is realising we can't please everyone at once.

This advice elaborates on the quote earlier to repeat code in order not to create dependencies, but not to manage them. Creating a separate API is one way to avoid dependencies to code that are hard to delete.

Sometimes it's easier to delete one big mistake than try to delete 18 smaller interleaved mistakes.

Sometimes it really is best to write a big chunk of code precisely because it is easy to delete. An idea that is distributed throughout a bunch of functions or modules has to be disentangled before you can delete it.

Becoming a professional software developer is accumulating a back-catalogue of regrets and mistakes.

I'm going to use this line in my spring Programming Languages class. There are unforeseen advantages to all the practice we profs ask students to do. That's where experience comes from.

We are not building modules around being able to re-use them, but being able to change them.

This is another good bit of advice for my students, though I'll write this one more clearly. When students learn to program, textbooks often teach them that the main reason to write a function is that you can reuse it later, thus saving the effort of writing similar code again. That's certainly one benefit of writing a function, but experienced programmers know that there are other big wins in creating functions, classes, and modules, and that these wins are often even more valuable than reuse. In my courses, I try to help students appreciate the value of names in understanding and modifying code. Modularity also makes it easier to change and, yes, delete code. Unfortunately, students don't always get the right kind of experience in their courses to develop this deeper understanding.

Although the single responsibility principle suggests that "each module should only handle one hard problem", it is more important that "each hard problem is only handled by one module".

Lovely. The single module that handles a hard problem is a point of leverage. It can be deleted when the problem goes away. It can be rewritten from scratch when you understand the problem better or when the context around the problem changes.

This line is the heart of the article:

The strategies I've talked about -- layering, isolation, common interfaces, composition -- are not about writing good software, but how to build software that can change over time.

Good software is software that can you can change. One way to create software you can change is to write code that you can easily replace.

Good code isn't about getting it right the first time. Good code is just legacy code that doesn't get in the way.

A perfect aphorism to close to the article, and to perfect way to close this post: Good code is legacy code that doesn't get in the way.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

December 26, 2018 2:44 PM

It's Okay To Say, "I Don't Know." Even Nobel Laureates Do It.

I ran across two great examples of humility by Nobel Prize-winning economists in recent conversations with Tyler Cowen. When asked, "Should China and Japan move to romanized script?", Paul Romer said:

I basically don't know the answer to that question. But I'll use that as a way to talk about something else ...

Romer could have speculated or pontificated; instead, he acknowledged that he didn't know the answer and pivoted the conversation to a related topic he had thought about (reforming spelling in English, for which he offered an interesting computational solution). By shifting the topic, Romer added value to the conversation without pretending that any answer he could give to the original question would have more value than as speculation.

A couple of months ago, Cowen sat with Paul Krugman. When asked whether he would consider a "single land tax" as a way to encourage a more active and more equitable economy, Krugman responded:

I just haven't done my homework on that.

... and left it there. To his credit, Cowen did not press for an uninformed answer; he moved on to another question.

I love the attitude that Krugman and Romer adopt and really like Krugman's specific answer, which echoed his response to another question earlier in the conversation. We need more people answering questions this way, more often and in more circumstances.

Such restraint is probably even more important in the case of Nobel laureates. If Romer and Klugman choose to speculate on a topic, a lot of people will pay attention, even if it is a topic they know little about. We might learn something from their speculations, but we might also forget that they are only uninformed speculation.

I think what I like best about these answers is the example that Romer and Klugman set for the rest of us: It's okay to say, "I don't know." If you have not done the homework needed to offer an informed answer, it's often best to say so and move on to something you're better prepared to discuss.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

December 23, 2018 10:45 AM

The Joy of Scholarship

This morning I read Tyler Cowen's conversation with Paul Romer. At one point, Romer talks about being introduced to C.S. Peirce, who had deep insights into "abstraction and how we use abstraction to communicate" (a topic Romer and Cowen discuss earlier in the interview). Romer is clearly enamored with Peirce's work, but he's also fascinated by the fact that, after a long career thinking about a set of topics, he could stumble upon a trove of ideas that he didn't even know existed:

... one of the joys of reading -- that's not a novel -- but one of the joys of reading, and to me slightly frightening thing, is that there's so much out there, and that a hundred years later, you can discover somebody who has so many things to say that can be helpful for somebody like me trying to understand, how do we use abstraction? How do we communicate clearly?

But the joy of scholarship -- I think it's a joy of maybe any life in the modern world -- that through reading, we can get access to the thoughts of another person, and then you can sample from the thoughts that are most relevant to you or that are the most powerful in some sense.

This process, he says, is the foundation for how we transmit knowledge within a culture and across time. It's how we grow and share our understanding of the world. This is a source of great joy for scholars and, really, for anyone who can read. It's why so many people love books.

Romer's interest in Peirce calls to mind my own fascination with his work. As Romer notes, Peirce had a "much more sophisticated sense about how science proceeds than the positivist sort of machine that people describe". I discovered Peirce through an epistemology course in graduate school. His pragmatic view of knowledge, along with William James's views, greatly influenced how I thought about knowledge. That, in turn, redefined the trajectory by which I approached my research in knowledge-based systems and AI. Peirce and James helped me make sense of how people use knowledge, and how computer programs might.

So I feel a great kinship with Romer in his discovery of Peirce, and the joy he finds in scholarship.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

November 28, 2018 1:56 PM

If it matters enough to be careful, it matters enough to build a system.

In Quality and Effort, Seth Godin reminds us that being careful can take us only so far toward the quality we seek. Humans make mistakes, so we need processes and systems in place to help us avoid them. Near the end of the post, he writes:

In school, we harangue kids to be more careful, and spend approximately zero time teaching them to build better systems instead. We ignore checklists and processes because we've been taught that they're beneath us.

This paragraph isolates one of the great powers we can teach our students, but also a glaring weakness in how most of us actually teach. I've been a professor for many years now, and before that I was a student for many years. I've seen a lot of students succeed and a few not do as well as they or I had hoped. Students who are methodical, patient, and disciplined in how they read, study, and program are much more likely to be in the successful group.

Rules and discipline sometimes get a bad rap these days. Creativity and passion are our catchwords. But dull, boring systems are often the keys that unlock the doors to getting things done and moving on to learn and do cooler things.

Students occasionally ask me why I slavishly follow the processes I teach them, whether it's a system as big as test-first development and refactoring or a process as simple as the technique for creating NFAs and converting them to DFAs. I tell them that I don't always trust myself but that I do trust the system: it almost always leads me to a working solution. Sure, in this moment or that I might be fine going off script, but... Good habits generate positive returns, while freewheeling it too often lets an error sneak in. (When I go off script in class, they too often get to see just that!)

We do our students a great favor when when we help them learn systems that work. Following a design recipe or something like it may be boring, but students who learn to follow it develop stronger programming skills, enjoy the success of getting projects done successfully, and graduate on to more interesting problems. As the system becomes ingrained as habit, they usually begin to appreciate it as an enabler of their success.

I agree with Godin: If it matters enough to be careful, then it matters enough to build (or learn) a system.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

November 25, 2018 10:50 AM

Seek Out Idea Amplifiers, Not Sound Absorbers

Richard Hamming -- he of Hamming codes, Hamming numbers, and Hamming distance -- wasn't a big fan of brainstorming. He preferred to talk about his ideas with another capable person, because the back-and-forth was more likely to help the idea reach "critical mass". But not every capable person is a good partner for such conversations:

There is also the idea I used to call 'sound absorbers'. When you get too many sound absorbers, you give out an idea and they merely say, "Yes, yes, yes." What you want to do is get that critical mass in action; "Yes, that reminds me of so and so," or, "Have you thought about that or this?" When you talk to other people, you want to get rid of those sound absorbers who are nice people but merely say, "Oh yes," and to find those who will stimulate you right back.

What a simple bit of advice: seek out idea amplifiers, not sound absorbers. Talk with people who help you expand and refine your ideas, by making connections to other work or by pushing you to consider implications or new angles. I think that talking to the right people can boost your work in another important way, too: they will feed your motivation, helping you to maintain the energy you need to stay excited and active.

This is one of the great benefits of blogs and Twitter, used well. We have so many more opportunities than ever before to converse with the right people. Unlike Hamming, I can't walk the halls of Bell Labs, or on any regular basis walk the halls of a big research university or one of the great computing companies. But I can read the blogs written by the researchers who work there, follow them on Twitter, and participate in amplifying conversations. Blogs and Twitter are great sources of both ideas and encouragement.

(The passage quoted above comes from the question-and-answer portion of Hamming's classic 1986 talk, You and Your Research. I re-read it this morning, as I occasionally do, because it's one of those papers that causes me to be more intentional in how I approach my work. Like Hamming, "I have a lot of faults", which means that there is considerable value to be found in judicious self-management. I need periodic booster shots.)

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Teaching and Learning

November 19, 2018 3:35 PM

Why Don't More CS Professors Use the Results of CS Education Research?

Over the last few days, there has been an interesting Twitter thread on the challenges of getting CS instructors to adopt the results of CS education research. Actually, it started as a thread and grew into a tree... Here's a reasonable jumping-in spot if you'd like to explore.

I imagine that it's hard to get research results into the classroom in a lot of disciplines. Research can be abstract and is usually out of context for any given school. But even when research groups implement curricula and train teachers, it can be hard to spread practices that we know work well.

The answer educators give for not adopting research results often boils down to, "It's complicated." Schools are different; students are different; the end goals are different. Indeed, the original Twitter thread spawned a student diversity conversation that picked up when the energy of the original topic waned. This tweet is a nice anchor for that conversation:

Majors vs. non-majors. Undergrads vs. high school vs. elementary school. Adult software developers vs end-user programmers vs conversational programmers. Different goals: authenticity, security, software engineering, algorithmic thinking, practice production. No one way.

All of these distinctions are real. I've seen several of them affect how we teach introductory programming at my school. And let's be honest: when we talk about research in CS education, we are often talking almost exclusively about teaching programming. How we teach intro programming can, though, have a big effect on student performance in later courses.

But even in the face of these different dimensions, I still wonder why more of us don't incorporate more research results into our teaching. I have a few ideas borne out of my years as a faculty member.

I think a big part of the effect that students have on whether faculty adopt new pedagogical approaches comes an angle not mentioned in that list: competitive pressure. Departments fear that if they adopt an unusual curriculum or an unusual first language, they will lose students. These fears manifest themselves if you propose to teach a relatively ordinary language such as Ada; they grow quickly if your approach uses an esoteric parentheses language (EPL). Parents of HS students will say, "Your competitors don't use EPL or your unusual pedagogical approach. They teach Good Old-Fashioned CS, the way it's always been, a way that's proven to get graduates jobs. Why shouldn't we send our daughters and sons to another school?"

HS students and their parents do ask questions such as these, and it takes a lot of perseverance to respond over and over. Only the most committed believers can stay the course. Unfortnately, it can take a few years for the benefits of a new approach to show up in upper division courses, let alone in the performance of graduates. New curricula rarely have that much time to succeed. If the department's faculty aren't all fully committed to an approach, then as soon as enrollments dip a bit, they join the chorus. There's a scapegoat ready at hand.

Even if we step back from the competitive disadvantage angle, we can see a similar phenomenon at play. The tweet quoted above list many different kinds of learners. These distinctions can serve as a handy reason for faculty not to change when faced with CS ed research that may only apply to one student population or one context. And resistance to change is a strong force.

Speaking as a long-time professor, I think the most powerful forces against change arise not on the student side of the equation but on the teachers'. Learning a bunch of new techniques, integrating them into a coherent curriculum, and then mastering them is hard. It takes time profs don't always have a lot of. When they do have some time, reading and applying CS ed research pulls them away from their own research or even away from the things they like to do in the classroom.

Personal confession time. This all reminds me of a conversation I had with Mike Clancy many years ago. He was part of the team that developed the idea of using case studies to teach programming. I've always admired the approach and thought the intro textbook he and Marcia Linn built around it was pretty cool. When I told Mike this, he asked, "Well then, why aren't you using them? Why aren't you writing case studies of your own?" These were great questions that took me aback. My answers sound like the excuses I've talked about in this post... My colleagues were skeptical of the approach and preferred other textbooks; convincing them to change would require a lot of work and political capital. Writing case studies is hard work, and at the time I was more excited to work on my own somewhat-related ideas. "Soon", I said. But soon never came.

I sit here still admiring case studies -- and worked examples, and Parsons problems, and the design recipe, and How to Design Programs. I've incorporated the idea of design recipes into my Programming Languages course, but I haven't fully committed to it yet. The others? They are still dreams. (I did try my first Parsons problem this semester: an assembly language program in my compilers course. I liked the result and think I'll try more next semester when I teach my students functional programming in Racket.)

Am I slow to adopt evidence-backed pedagogy? Lazy? Short on time? I don't know, but I suspect that there are many reasons. Change is hard. I do hope that I haven't done my students too much disservice in the meantime.

At one point in the Twitter conversation that launched this post, someone wrote something to the effect, "convincing researchers is easier than convincing practitioners". But that brings to mind another question: Why aren't all CS ed researchers advocating the use of worked examples? Design recipe and HTDP-style curricula? Parsons problems? Why aren't more CS ed researchers using them in their own classrooms? Maybe they are and I haven't been paying attention. If that's so, then I doubt that many other CS profs know about this widespread adoption of advances among CS ed researchers either.

Some disciplines, such as physics, seem to have developed more of a culture for incorporating education research into the classroom than computer science. Can we change that? If so, I think there is room for the CS ed research community to lead the way. But... it's complicated.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

October 21, 2018 9:53 AM

Find the Hard Work You're Willing to Do

I like this passage from John Urschel Goes Pro, about the former NFL player who is pursuing a Ph.D. in math:

The world thinks mathematicians are people for whom math is easy. That's wrong. Sure, some kids, like Urschel, have little trouble with school math. But everyone who starts down the road to creating really new mathematics finds out what Urschel did: It's a struggle. A prickly, sometimes lonely struggle whose rewards are uncertain and a long time coming. Mathematicians are the people who love that struggle.

It's cliché to tell kids to "find their passion". That always seems to me like an awful lot of pressure to put on young adults, let alone teenagers. I meet with potential CS majors frequently, both college students and high school students. Most haven't found their passion yet, and as a result many wonder if there is something wrong with them. I do my my best to assure them that, no, there is nothing wrong with them. It's an unreasonable expectation placed on them by a world that, usually with good intentions, is trying to encourage them.

I don't think there is anything I'd rather be than a computer scientist, but I did not walk a straight path to being one. Some choices early on were easy: I like biology as a body of knowledge, but I never liked studying biology. That seemed a decent sign that maybe biology wasn't for me. (High-school me didn't understand that there might be a difference between school biology and being a biologist...) But other choices took time and a little self-awareness.

From the time I was eight years old or so, I wanted to be an architect. I read about architecture; I sent away for professional materials from the American Institute of Architects; I took courses in architectural drafting at my high school. (There was an unexpected benefit to taking those courses: I got to meet a lot of people were not part of my usual academic crowd.) Then I went off to college to study architecture... and found that, while I liked many things about the field, I didn't really like to do the grunt work that is part of the architecture student's life, and when the assigned projects got more challenging, I didn't really enjoy working on them.

But I had enjoyed working on the hard projects I'd encountered in my programing class back in high school. They were challenges I wanted to overcome. I changed my major and dove into college CS courses, which were full of hard problems -- but hard problems that I wanted to solve. I didn't mind being frustrated for an entire semester one year, working in assembly language and JCL, because I wanted to solve the puzzles.

Maybe this is what people mean when they tell us to "find our passion", but that phrase seems pretty abstract to me. Maybe instead we should encourage people to find the hard problems they like to work on. Which problems do you want to keep working on, even when they turn out to be harder than you expected? Which kinds of frustration do you enjoy, or at least are willing to endure while you figure things out? Answers to these very practical questions might help you find a place where you can build an interesting and rewarding life.

I realize that "Find your passion" makes for a more compelling motivational poster than "What hard problems do you enjoy working on?" (and even that's a lot better than "What kind of pain are you willing to endure?"), but it might give some people a more realistic way to approach finding their life's work.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

October 05, 2018 3:39 PM

Why Patterns Failed and Why You Should Care

Beds are useful. I enjoyed my bed at the hotel last night. But you won't find a pattern called bed in A Pattern Language, and that's because we don't have a problem with beds. Beds are solved. What we have a problem with is building with beds. And that's why, if you look in A Pattern Language, you'll find there are a number of patterns that involve beds.

Now, the analogy I want to make is, basically, the design patterns in the book Design Patterns are at the same level as the building blocks in the book A Pattern Language. So Bridge, which is one of the design patterns, is the same kind of thing as column. You can call it a pattern, but it's not really a pattern that gets at the root problem we're trying to solve. And if Alexander had written a book that had a pattern called Bed and another one called Chair, I imagine that that book would have failed and not inspired all of the people that the actual book did inspire. So that, I claim, is why patterns failed.

Those two nearly-sequential paragraphs are from Patterns Failed. Why? Should We Care?, a talk Brian Marick gave at Deconstruct 2017. It's a good talk. Marick's provocative claim that, as an idea, software patterns failed is various degrees of true and false depending on how you define 'patterns' and 'failed'. It's hard to declare the idea an absolute failure, because a lot of software developers and UI designers use patterns to good effect as a part of their work every day. But I agree with Brian that software patterns failed to live up to their promise or to the goals of the programmers who worked so hard to introduce Christopher Alexander's work to the software community. I agree, too, that the software pattern community's inability to document and share patterns at the granularity that made Alexander's patterns so irresistible is a big part of why.

I was a second- or third-generation member of the patterns community, joining in after Design Patterns had been published and, like Marick, I worked mostly on the periphery. Early on I wrote patterns that related to my knowledge-based systems work. Much of my pattern-writing, though, was at the level of elementary patterns, the patterns that novice programmers learn when they are first learning to program. Even at that level, the most useful patterns often were ones that operated up one level from the building blocks that novices knew.

Consider Guarded Linear Search, from the Loop Patterns paper that Owen Astrachan and I workshopped at PLoP 1998. It helps beginners learn how to arrange a loop and an if statement in a way that achieves a goal. Students in my beginning courses often commented how patterns like this one helped them write programs because, while they understood if statements and for statements and while statements, they didn't always know what to do with them when facing a programming task. At that most elementary level, the Guarded Linear Search pattern was a pleasing -- and useful -- whole.

That said, there aren't many "solved problems" for beginners, so we often wrote patterns that dropped down to the level of building blocks simply to help novices learn basic constructs. Some of the Loop Patterns paper does that, as does Joe Bergin's Patterns for Selection. But work in the elementary patterns community would have been much more valuable, and potentially had more effect, if we had thought harder about how to find and document patterns at the level of Alexander's patterns.

Perhaps the patterns sub-community in which I've worked in which best achieved its goals was the pedagogical patterns community. These are not software patterns but rather patterns of teaching techniques. They document solutions to problems that teachers face every day. I think I'd be willing to argue that the primary source of pedagogical patterns' effectiveness is that these solutions combine more primitive building blocks (delivery techniques, feedback techniques, interaction techniques) in a way that make learning and instruction both more effective and more fun. As a result, they captured a lot of teachers' interest.

I think that Marick's diagnosis also points out the error in a common criticism of software patterns. Over the years, we often heard folks say that software patterns existed only because people used horrible languages like C++ and Java. In a more powerful language, any purported pattern would be implemented as a language primitive or could be made a primitive by writing a macro. But this misses the point of Alexander's insight. The problem in software development isn't with inheritance and message passing and loops, just as the problem in architecture isn't with beds and windows and space. It's with finding ways to arrange these building blocks in a way that's comfortable and nice and, to use Alexander's term, "life-giving". That challenge exists in all programming languages.

Finally, you probably won't be surprised to learn that I agree with Marick that we should all care that software patterns failed to live up to their promise. Making software is fun, but it's also challenging. Alexander's idea of a pattern language is one way that we might help programmers do their jobs better, enjoy their jobs more, and produce software that is both functional and habitable. The first pass was a worthy effort, and a second pass, informed by the lessons of the first, might get us closer to the goal.

Thanks to Brian for giving this talk and to the folks at Deconstruct for posting it online. Go watch it.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

September 30, 2018 10:31 AM

Strange Loop 2: Simon Peyton Jones on Teaching CS in the Schools

Simon Peyton discusses one of the myths of getting CS into the primary and secondary classroom: it's all about the curriculum

The opening keynote this year was by Simon Peyton Jones of Microsoft Research, well known in the programming languages for Haskell and many other things. But his talk was about something considerably less academic: "Shaping Our Children's Education in Computing", a ten-year project to reform the teaching of computing in the UK primary and secondary schools. It was a wonderful talk, full of history, practical advice, lessons learned, and philosophy of computing. Rather than try to summarize everything Peyton Jones said, I will let you watch the video when it is posted (which will be as early as next week, I think).

I would, though, like to highlight one particular part of the talk, the way he describes computer science to a non-CS audience. This is an essential skill for anyone who wants to introduce CS to folks in education, government, and the wider community who often see CS as either hopelessly arcane or as nothing more than a technology or a set of tools.

Peyton Jones characterized computing as being about information, computation, and communication. For each, he shared one or two ways to discuss the idea with an educated but non-technical audience. For example:

  • Information.   Show two images, say the Mona Lisa and a line drawing of a five-pointed star. Ask which contains more information. How can we tell? How can we compare the amounts? How might we write that information down?

  • Computation.   Use a problem that everyone can relate to, such as planning a trip to visit all the US state capitals in the fewest miles or sorting a set of numbers. For the latter, he used one of the activities from CS Unplugged on sorting networks as an example.

  • Communication.   Here, Peyton Jones used the elegant and simple idea underlying the Diffie Hellman algorithm for sharing secret as his primary example. It is simple and elegant, yet it's not at all obvious to most people who don't already know it that the problem can be solved at all!

In all three cases, it helps greatly to use examples from many disciplines and to ask questions that encourage the audience to ask their own questions, form their own hypotheses, and create their own experiments. The best examples and questions actually enable people to engage with computing through their own curiosity and inquisitiveness. We are fascinated by computing; other people can be, too.

There is a huge push in the US these days for everyone to learn how to program. This creates a tension among many of us computer scientists, who know that programming isn't everything that we do and that its details can obscure CS as much as they illuminate it. I thought that Peyton Jones used a very nice analogy to express the relationship between programming and CS more broadly: Programming is to computer science as lab work is to physics. Yes, you could probably take lab work out of physics and still have physics, but doing so would eviscerate the discipline. It would also take away a lot of what draws people to the discipline. So it is with programming and computer science. But we have to walk a thin line, because programming is seductive and can ultimately distract us from the ideas that make programming so valuable in the first place.

Finally, I liked Peyton Jones's simple summary of the reasons that everyone should learn a little computer science:

  • Everyone should be able to create digital media, not just consume it.
  • Everyone should be able to understand their tools, not just use them.
  • People should know that technology is not magic.
That last item grows increasingly important in a world where the seeming magic of computers redefines every sector of our lives.

Oh, and yes, a few people will get jobs that use programming skills and computing knowledge. People in government and business love to hear that part.

Regular readers of this blog know that I am a sucker for aphorisms. Peyton Jones dropped a few on us, most earnestly when encouraging his audience to participate in the arduous task of introducing and reforming the teaching CS in the schools:

  • "If you wait for policy to change, you'll just grow old. Get on with it."
  • "There is no 'them'. There is only us."
(The second of these already had a home in my brain. My wife has surely tired of hearing me say something like it over the years.)

It's easy to admire great researchers who have invested so much time and energy into solving real-world problems, especially in our schools. As long as this post is, it covers only a few minutes from the middle of the talk. My selection and bare-bones outline don't do justice to Peyton Jones's presentation or his message. Go watch the talk when the video goes up. It was a great way to start Strange Loop.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

September 20, 2018 4:44 PM

Special Numbers in a Simple Language

This fall I am again teaching our course in compiler development. Working in teams of two or three, students will implement from scratch a complete compiler for a simple functional language that consists of little more than integers, booleans, an if statement, and recursive functions. Such a language isn't suitable for much, but it works great for writing programs that do simple arithmetic and number theory. In the past, I likened it to an integer assembly language. This semester, my students are compiling a Pascal-like language of this sort that call Flair.

If you've read my blog much in the falls over the last decade or so, you may recall that I love to write code in the languages for which my students write their compilers. It makes the language seem more real to them and to me, gives us all more opportunities to master the language, and gives us interesting test cases for their scanners, parsers, type checkers, and code generators. In recent years I've blogged about some of my explorations in these languages, including programs to compute Farey numbers and excellent numbers, as well as trying to solve one of my daughter's AP calculus problems.

When I run into a problem, I usually get an itch to write a program, and in the fall I want to write it in my students' language.

Yesterday, I began writing my first new Flair program of the semester. I ran across this tweet from James Tanton, which starts:

N is "special" if, in binary, N has a 1s and b 0s and a & b are each factors of N (so non-zero).

So, 10 is special because:

  • In binary, 10 is 1010.
  • 1010 contains two 1s and two 0s.
  • Two is a factor of 10.

9 is not special because its binary rep also contains two 1s and two 0s, but two is not a factor of 9. 3 is not special because its binary rep has no 0s at all.

My first thought upon seeing this tweet was, "I can write a Flair program to determine if a number is special." And that is what I started to do.

Flair doesn't have loops, so I usually start every new program by mapping out the functions I will need simply to implement the definition. This makes sure that I don't spend much time implementing loops that I don't need. I ended up writing headers and default bodies for three utility functions:

  • convert a decimal number to binary
  • count the number of times a particular digits occurs in a number
  • determine if a number x divides evenly into a number n

With these helpers, I was ready to apply the definition of specialness:

    return divides(count(1, to_binary(n)), n)
       and divides(count(0, to_binary(n)), n)

Calling to_binary on the same argument is wasteful, but Flair doesn't have local variables, either. So I added one more helper to implement the design pattern "Function Call as Variable Assignment", apply_definition:

    function apply_definition(binary_n : integer, n : integer) : boolean
and called it from the program's main:
    return apply_definition(to_binary(n), n)

This is only the beginning. I still have a lot of work to do to implement to_binary, count and divides, using recursive function calls to simulate loops. This is another essential design pattern in Flair-like languages.

As I prepared to discuss my new program in class today, I found bug: My divides test was checking for factors of binary_n, not the decimal n. I also renamed a function and one of its parameters. Explaining my programs to students, a generalization of rubber duck debugging, often helps me see ways to make a program better. That's one of the reasons I like to teach.

Today I asked my students to please write me a Flair compiler so that I can run my program. The course is officially underway.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Teaching and Learning

September 05, 2018 3:58 PM

Learning by Copying the Textbook

Or: How to Learn Physics, Professional Golfer Edition

Bryson DeChambeau is a professional golfer, in the news recently for consecutive wins in the FedExCup playoff series. But he can also claim an unusual distinction as a student of physics:

In high school, he rewrote his physics textbook.

DeChambeau borrowed the textbook from the library and wrote down everything from the 180-page book into a three-ring binder. He explains: "My parents could have bought one for me, but they had done so much for me in golf that I didn't want to bother them in asking for a $200 book. ... By writing it down myself I was able to understand things on a whole comprehensive level.

I imagine that copying texts word-for-word was a more common learning strategy back when books were harder to come by, and perhaps it will become more common again as textbook prices rise and rise. There is certainly something to be said for it. Writing by hand takes time, and all the while our brains can absorb terms, make connections among concepts, and process the material into long-term memory. Zed Shaw argues for this as a great way to learn computer programming, implementing it as a pedagogical strategy in his "Learn <x> the Hard Way" series of books. (See Learn Python the Hard Way as an example.)

I don't think I've ever copied a textbook word-for-word, and I never copied computer programs from "Byte" magazine, but I do have similar experiences in note taking. I took elaborate notes all through high school, college, and grad school. In grad school, I usually rewrote all of my class notes -- by hand; no home PC -- as I reviewed them in the day or two after class. My clean, rewritten notes had other benefits, too. In a graduate graph algorithms course, they drew the attention of a classmate who became one of my best friends and were part of what attracted the attention of the course's professor, who asked me to consider joining his research group. (I was tempted... Graph algorithms was one of my favorite courses and research areas!)

I'm not sure many students these days benefit from this low-tech strategy. Most students who take detailed notes in my course seem to type rather than write which, if what I've read is correct, has fewer cognitive advantages. But at least those students are engaging with the material consciously. So few students seem to take detailed notes at all these days, and that's a shame. Without notes, it is harder to review ideas, to remember what they found challenging or puzzling in the moment, and to rehearse what they encounter in class into their long-term memories. Then again, maybe I'm just having a "kids these days" moment.

Anyway, I applaud DeChambeau for saving his parents a few dollars and for the achievement of copying an entire physics text. He even realized, perhaps after the fact, that it was an excellent learning strategy.

(The above passage is from The 11 Most Unusual Things About Bryson DeChambeau. He sounds like an interesting guy.)

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

August 31, 2018 3:06 PM

Reflection on a Friday

If you don't sit facing the window, you could be in any town.

I read that line this morning in Maybe the Cumberland Gap just swallows you whole, where it is a bittersweet observation of the similarities among so many dying towns across Appalachia. It's a really good read, mostly sad but a little hopeful, that applies beyond one region or even one country.

My mind is self-centered, though, and immediately reframed the sentence in a way that cast light on my good fortune.

I just downloaded a couple of papers on return-oriented programming so that I can begin working with an undergraduate on an ambitious research project. I have a homework assignment to grade sitting in my class folder, the first of the semester. This weekend, I'll begin to revise a couple of lectures for my compiler course, on NFAs and DFAs and scanning text. As always, there is a pile of department work to do on my desk and in my mind.

I live in Cedar Falls, Iowa, but if I don't sit facing the window, I could be in Ames or Iowa City, East Lansing or Durham, Boston or Berkeley. And I like the view out of my office window very much, thank you, so I don't even want to trade.

Heading into a three-day weekend, I realize again how fortunate I am. Do I put my good fortune to good enough use?

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

August 17, 2018 2:19 PM

LangSec and My Courses for the Year

As I a way to get into the right frame of mind for the new semester and the next iteration of my compiler course, I read Michael Hicks's Software Security is a Programming Languages Issue this morning. Hicks incorporates software security into his courses on the principles of programming languages, with two lectures on security before having students study and use Rust. The article has links to lecture slides and supporting material, which makes it a post worth bookmarking.

I started thinking about adding LangSec to my course late in the spring semester, as I brainstormed topics that might spice the rest of the course up for both me and my students. However, time was short, so I stuck with a couple of standalone sessions on topics outside the main outline: optimization and concatenative languages. They worked fine but left me with an itch for something new.

I think I'll use the course Hicks and his colleagues teach as a starting point for figuring out how I might add to next spring's course. Students are interested in security, it's undoubtedly an essential issue for today's grads, and it is a great way to demonstrate how the design of programming languages is more than just the syntax of a loop or the lambda calculus.

Hicks's discussion of Rust also connects with my fall course. Two years ago, an advanced undergrad used Rust as the implementation language for his compiler. He didn't know the language but wanted to pair it with Haskell in his toolbox. The first few weeks of the project were a struggle as he wrestled with mastering ownership and figuring out some new programming patterns. Eventually he hit a nice groove and produced a working compiler with only a couple of small holes.

I was surprised how easy it was for me install the tools I needed to compile, test, and explore his code. That experience increased my interest in learning the language, too. Adding it to my spring course would give me the last big push I need to buckle down.

This summer has been a blur of administrative stuff, expected and unexpected. The fall semester brings the respite of work I really enjoy: teaching compilers and writing some code. Hurray!

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

August 09, 2018 1:03 PM

Gerald Weinberg Has Passed Away

I just read on the old Agile/XP mailing list that Jerry Weinberg passed away on Tuesday, August 7. The message hailed Weinberg as "one of the finest thinkers on computer software development". I, like many, was a big fan of work.

My first encounter with Weinberg came in the mid-1990s when someone recommended The Psychology of Computer Programming to me. It was already over twenty years old, but it captivated me. It augmented years of experience in the trenches developing computer software with a deep understanding of psychology and anthropology and the firm but gentle mindset of a gifted teacher. I still refer back to it after all these years. Whenever I open it up to a random page, I learn something new again. If you've never read it, check it out now. You can buy the ebook -- along with many of Weinberg's books -- online through LeanPub.

After the first book, I was hooked. I never had the opportunity to attend one of Weinberg's workshops, but colleagues lavished them with praise. I should have made more of an effort to attend one. My memory is foggy now, but I do think I exchanged email messages with him once back in the late 1990s. I'll have to see if I can dig them up in one of my mail archives.

Fifteen years ago or so, I picked up a copy of Introduction to General Systems Thinking tossed out by a retiring colleague, and it became the first in a small collection of Weinberg books now on my shelf. As older colleagues retire in the coming years, I would be happy to salvage more titles and extend my collection. It won't be worth much on the open market, but perhaps I'll be able to share my love of Weinberg's work with students and younger colleagues. Books make great gifts, and more so a book by Gerald Weinberg.

Perhaps I'll share them with my non-CS friends and family, too. A couple of summers back, my wife saw a copy of Are Your Lights On?, a book Weinberg co-wrote with Donald Gause, sitting on the floor of my study at home. She read it and liked it a lot. "You get to read books like that for your work?" Yes.

I just read Weinberg's final blog entry earlier this week. He wasn't a prolific blogger, but he wrote a post every week or ten days, usually about consulting, managing, and career development. His final post touched on something that we professors experience at least occasionally: students sometimes solve the problems we et before them better than we expected, or better than we ourselves can do. He reminded people not to be defensive, even if it's hard, and to see the situation as an opportunity to learn:

When I was a little boy, my father challenged me to learn something new every day before allowing myself to go to bed. Learning new things all the time is perhaps the most important behavior in my life. It's certainly the most important behavior in our profession.

Weinberg was teaching us to the end, with grace and gratitude. I will miss him.

Oh, and one last personal note: I didn't know until after he passed that we shared the same birthday, a few years apart. A meaningless coincidence, of course, but it made me smile.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

July 31, 2018 4:23 PM

Software Projects, Potential Employers, and Memories

I spent a couple of hours this morning at a roundtable discussion listening to area tech employers talk about their work and their companies' needs. It was pretty enjoyable (well, except perhaps for the CEO who too frequently prefaced his remarks with "What the education system needs to understand is ..."). To a company, they all place a lot of value on the projects that job candidates have done. Their comments reminded me of an old MAA blog post in which a recent grad said:

During the fall of my junior year, I applied for an internship at Red Ventures, a data analytics and technology company just outside Charlotte. Throughout the rigorous interview process, it wasn't my GPA that stood out. I stood out among the applicants, in part, because I was able to discuss multiple projects I had taken ownership of and was extremely passionate about.

I encourage this mentality in my students, though I think "passionate about" is too strong a condition (not to mention cliché). Students should have a few projects that they are interested in, or proud of, or maybe just completed.

Most of the students taking my compiler course this fall won't be applying for a compiler job when they graduate, but they will have written a compiler as part of a team. They will have met a spec, collaborated on code, and delivered a working product. That is evidence of skill, to be sure, but also of hard work and persistence. It's a significant accomplishment.

The students who take our intelligent systems course or our real-time embedded systems will be able to say the same thing. Some students will also be able to point to code they wrote for a club or personal projects. They key is to build things, care about them, and "deliver", whatever that means in the context of that particular project.

I made note of one new piece of advice to give our students, offered by a former student I mentioned in a blog post many years ago who is now head of a local development team for mobile game developer Jam City: Keep all the code you write. It can be a GitHub repo, as many people now recommend, but it doesn't have to be. A simple zip file organized by courses and projects can be enough. Such a portfolio can show prospective employers what you've done, how you've grown, and how much you care about the things you make. It can say a lot.

You might even want to keep all that code for Future You. I'm old enough that it was difficult to keep digital copies of all the code I wrote in college. I have a few programs from my undergrad days and a few more from grad school, which have migrated across storage media as time passed, but I missing much of my class work as a young undergrad and all of the code I wrote in high school. I sometimes wish I could look back at some of that code...

Posted by Eugene Wallingford | Permalink | Categories: Personal, Software Development, Teaching and Learning

July 17, 2018 2:32 PM

Get Attached to Solving Problems for People

In Getting Critiqued, Adam Morse reflects on his evolution from art student to web designer, and how that changed his relationship with users and critiques. Artists create things in which they are, at some level, invested. Their process matters. As a result, critiques, however well-intentioned, feel personal. The work isn't about a user; it's about you. But...

... design is different. As a designer, I don't matter. My work doesn't matter. Nothing I make matters in the context of my process. It's all about the people you are building for. You're just trying to solve problems for people. Once you realize this, it's the most liberating thing.

Now, criticism isn't really about you as artist. It's about how well the design meets the needs of the user. With that in mind, the artist can put some distance between himself or herself and think about the users. That's probably what the users are paying for anyway.

I've never been a designer, but I was fortunate to learn how better to separate myself from my work by participating in the software patterns community and its writers' workshop format. From the workshops, I came to appreciate the value of providing positive and constructive feedback in a supportive way. But I also learned to let critiques from others be about my writing and not about me. The ethos of writers' workshops is one of shared commitment to growth and so creates as supportive framework as possible in which to deliver suggestions. Now, even when I'm not in such an conspicuously supportive environment, I am better able to detach myself from my work. It's never easy, but it's easier. This mindset can wear off a bit over time, so I find an occasional inoculation via PLoP or another supportive setting to be useful.

Morse offers another source of reminder: the designs we create for the web -- and for most software, too-- are not likely to last forever. So...

Don't fall in love with borders, gradients, a shade of blue, text on blurred photos, fancy animations, a certain typeface, flash, or music that autoplays. Just get attached to solving problems for people.

That last sentence is pretty good advice for programmers and designers alike. If we detach ourselves from our specific work output a bit and instead attach ourselves to solving problems for other people, we'll be able to handle their critiques more calmly. As a result, we are also likely to do better work.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

June 29, 2018 11:46 AM

Computer Science to the Second Degree

Some thoughts on studying computer science from Gian-Carlo Rota:

A large fraction of MIT undergraduates major in computer science or at least acquire extensive computer skills that are applicable in other fields. In their second year, they catch on to the fact that their required courses in computer science do not provide the whole story. Not because of deficiencies in the syllabus; quite the opposite. The undergraduate curriculum in computer science at MIT is probably the most progressive and advanced such curriculum anywhere. Rather, the students learn that side by side with required courses there is another, hidden curriculum consisting of new ideas just coming into use, new techniques and that spread like wildfire, opening up unsuspected applications that will eventually be adopted into the official curriculum.

Keeping up with this hidden curriculum is what will enable a computer scientist to stay ahead in the field. Those who do not become computer scientists to the second degree risk turning into programmers who will only implement the ideas of others.

MIT is, of course, an exceptional school, but I think Rota's comments apply to computer science at most schools. So much learning of CS happens in the spaces between courses: in the lab, in the student lounge, at meetings of student clubs, at part-time jobs, .... That can sometimes be a challenge for students who don't have much curiosity, or develop one as they are exposed to new topics.

As profs, we encourage students to be aware of all that is going on in computer science beyond the classroom and to take part in the ambient curriculum to the extent they are able. Students who become computer scientists only to the first degree can certainly find good jobs and professional success, but there are more opportunities open at the second degree. CS can also be a lot more fun there.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

June 03, 2018 10:50 AM

Two Thoughts on Teaching

... from my morning reading.

First, a sentence from Bryan Caplan, about one of his influences, philosopher Michael Huemer:

I think what's great about this book, and really all of Mike's work, is he always tries to start off with premises that make sense to people who don't already agree, and then try to get somewhere.

I value people who take the time to construct arguments in this way. It's surprisingly rare in academic discourse and public discourse. Teachers usually learn pretty quickly, though, that the most effective way to teach is start where your students are: recognize the state of their knowledge and respect their current beliefs. I try to remind myself of this principle regularly during a course, or I'm likely to go off track.

Second, the closing exchange from a 1987 interview with Stanley Kubrick. Kubrick has been talking about how the critics' views of his films tend to evolve over time. The interviewer wrapped up the conversation with:

Well, you don't make it easy on viewers or critics. You create strong feelings, but you won't give us any easy answers.

That's because I don't have any easy answers.

That seems like a pretty good aspiration to have for teaching, that people can say it creates strong feelings but doesn't give any easy answers. Much of teaching is simpler than this, of course, especially in a field such as computer science. A closure is something that we can understand as it is, as is, say, an algorithm for parsing a stream of tokens. But after you learn a few concepts and start trying to build or understand a complex system, easy answers are much harder to come by. Even so, I do hope that students leave my courses with strong feelings about their craft. Those feelings may not match my own, and they'll surely still be evolving, but they will be a product of the student engaging with some big ideas and trying them out on challenging problems.

Maybe if I keep reading interested articles on the exercise the bike and making connections to my craft, I can get this computer science thing down better.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

June 01, 2018 3:05 PM

Prepare to Appreciate the Solution

This post isn't really about chess, though it might seem at first to be.

In The Reviled Art, chess grandmaster Stuart Rachels says that most grandmasters don't like composed chess problems because they are too difficult. It's easy to imagine why average chessplayers find problems too difficult: they aren't all that great chess. But why grandmasters? Rachels contends that problems are hard for tournament players because they are counterintuitive: the solutions contradict the intuitions developed by players whose chess skill is developed and sharpened over the board.

Rachels then says:

Most problems stump me too, so I conceive of the time I spend looking at them as time spent preparing to appreciate their solutions -- not as time spent trying to solve them.

I love this attitude. If I view time spent banging my head against a puzzle or a hard problem as "trying to solve the problem", then not solving the problem might feel like failure. If I view that time as "preparing to appreciate the solution", then I can feel as if my time was well spent even if I don't solve it -- as long as I can appreciate the beauty or depth or originality of the solution.

This attitude is helpful outside of chess. Maybe I'm trying to solve a hard programming problem or trying to understand a challenging area of programming language theory that is new to me. I don't always solve the problem on my own or completely understand the new area without outside help or lots of time reading and thinking. But I often do appreciate the solution once I see it. All the time I spent working on the problem prepared me for that moment.

I often wish that more of my students would adopt Rachels's attitude. I frequently pose a problem for them to work on for a few minutes before we look at a solution, or several candidates, as a group. All too often some students look at the problem, think it's too difficult, and then just sit there waiting for me to show them the answer. This approach often results in them feeling two kinds of failure: they didn't solve the problem, and they don't even appreciate the solution when they see it. They haven't put in the work thinking about it that prepares their minds to really get the solution. Maybe I can do more to help students realize that the work is worth worth the effort even if they don't think they can solve the problem. Send me your suggestions!

Rachels's point about the counterintuitiveness of composed chess problems indicates another way in which trying to solve unorthodox problems can be worthwhile. Sometimes our intuitions let us down because they are too narrow, or even wrong. Trying to solve an unorthodox problem can help us broaden our thinking. My experience with chess compositions is that most of the ideas I need to solve them will not be helpful in over-the-board play; those kinds of positions simply don't occur in real games. But a few themes do apply, and practicing with them helps me learn how to play better in game situations. If nothing else, working on unorthodox problems reminds me to look outside the constraints of my intuitions sometimes when a problem in real life seems too hard.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

May 18, 2018 1:24 PM

Sharing Control

Sidney Lumet, in his book Making Movies, writes:

Arthur Miller's first, and I think, only novel, Focus, was, in my opinion, every bit as good as his first produced play, All My Sons. I once asked him why, if he was equally talented in both forms, he chose to write plays. Why would he give up the total control of the creative process that a novel provides to write instead for communal control, where a play would first go into the hands of a director and then pass into the hands of a cast, set designer, producer, and so forth? His answer was touching. He loved seeing what his work evoked in others. The result could contain revelations, feelings, and ideas that he never knew existed when he wrote the play. That's what he hoped for.

Writing software for people to use is something quite different from writing a play for audiences to watch, but this paragraph brought to mind experiences I had as a grad student and new faculty member. As a part of my doctoral work, I implemented a expert system shells for a couple of problem-solving styles. Experts and grad students in domains such as chemical engineering, civil engineering, education, manufacturing, and tax accounting used these shells to build expert systems in their domains. I often found myself in the lab with these folks as they used my tools. I learned a lot by watching them and discussing with them the languages implemented in the tools. Their comments and ideas sometimes changed how I thought about the languages and tools, and I was able to fold some of these changes back into the systems.

Software design can be communal, too. This is, of course, one of the cornerstones of agile software development. Giving up control can help us write better software, but it can also be a source of the kind of pleasure I imagine Miller got from working to bring his plays to life on stage.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

May 09, 2018 4:02 PM


In an old blog post promoting his book on timing, Daniel Pink writes:

... Connie Gersick's research has shown that group projects rarely progress in a steady, linear way. Instead, at the beginning of a project, groups do very little. Then at a certain moment, they experience a sudden burst of activity and finally get going. When is that moment? The temporal midpoint. Give a team 34 days, they get started in earnest on day 17. Give a team 11 days, they get really get going on day 6. In addition, there’s other research showing that being behind at the midpoint--in NBA games and in experimental settings--can boost performance in the second half.

So we need to recognize midpoints and try to use them as a spark rather than a slump.

I wonder if this research suggests that we should favor shorter projects over longer ones. If most of us start going full force only at the middle of our projects, perhaps we should make the middle of our projects come sooner.

I'll admit that I have a fondness for short over long: short iterations over long iterations in software development, quarters over semesters in educational settings, short books (especially non-fiction) over long books. Shorter cycles seem to lead to higher productivity, because I spend more time working and less time ramping up and winding down. That seems to be true for my students and faculty colleagues, too.

In the paragraph that follows the quoted passage, Pink points inadvertently to another feature of short projects that I appreciate: more frequent beginnings and endings. He talks about the poignancy of endings, which adds meaning to the experience. On the other end of the cycle are beginnings, which create a sense of newness and energy. I always look forward to the beginning of a new semester or a new project for the energy it brings me.

Agile software developers know that, on top of these reasons, short projects offer another potent advantage: more opportunities to take stock of what we have learned and feed that learning back into what we do.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

May 08, 2018 4:45 PM

"Tell Me Something You Learned"

I spent big chunks of the last two days grading final projects and final exams for my Programming Languages course. Grading exams is important but not a lot of fun, so I released a little tension on Twitter as thoughts popped into my head:

I love final exam answers that appear to be randomly generated from a list of terms learned in the course.

Also fun: code that appears to be randomly generated from a list of functions learned in the course.

... and then a student surprises me with a creative, efficient solution. I like those answers just as much.

Answer of the day so far: "Local variables help us be more ambiguous solving many problems at once."

I don't know what that means, but I love it.

I hope folks did not think I was "punching down". I know how stressful final exams are for most students, and I know how challenging a comprehensive final exam in this course is. Students have to write code, explain ideas, and connect ideas to code. It's tough. The tweets were just me having a little fun during what is otherwise a slow, laborious process.

This exam ended differently than any of the previous finals in this course. The final question, worth 5% of the exam grade, was this:

Identify one topic from the course that is not covered by an exam question but about which you learned something valuable. Write two to three sentences about what you learned.

I used to include a more wide-ranging version of this question to end my AI final exams many years ago, in which students had a chance to write a summary of the important ideas they had learned in the course. I'm not sure what reminded of the idea (perhaps one of James Tanton's essays), but this seemed like a nice way to give students a chance to boost their grades without a curve. I figured I would be generous and give them some latitude with their own experiences. My hope was that students could end the exam on a good note, feeling positive about something they learned and appreciated rather than solving yet another problem I fished out of fifteen weeks of material. There was a small risk -- what if a bunch of them panicked at the unusual question and couldn't think of anything to say? But that risk exists for almost any question I ask.

The question seems to have gone over quite well. Some students talked about a specific topic from the course, among them variable arity functions, currying, higher-order procedures, and syntactic abstraction. That's mostly what I had in mind when I wrote the question, even if some of their answers were covered in part somewhere else on the exam. Others answered more generally than I expected. A couple talked about how the course gave them a deeper appreciation for data abstraction; a couple of others wrote about the experience of writing an interpreter and having to live with their design decisions as the code as it grew over three weeks. All but one student wrote an answer substantive and reflective enough that I didn't even have to think about how many points to award. I was happy to read them.

I really shouldn't have been surprised. Most students care more about their learning, and get more out of a class, than exam answers and classroom participation might indicate. They face a lot of pressures, and as a result have a limited amount of time and energy to express about any one course day in and day out. But making software matters to most of them; sometimes even big ideas matter. This question let them express some of what made the class work for them.

This problem had unexpected effect... I ended the exam on a good note. I put down my grading pen feeling good about the course, knowing that each student learned something that stood out to them, that they appreciated enough to write a few sentences about. I got a small glimpse of how they changed as a result of the course. I put the question on the exam for the students' sake, but it affected me as much as it affected them.

That's not a bad way to end the semester.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

April 17, 2018 4:25 PM

The Tension Among Motivation, Real Problems, and Hard Work

Christiaan Huygens's first pendulum clock

In today's edition of "Sounds great, but...", I point you to Learn calculus like Huygens, a blog entry that relates some interesting history about the relationship between Gottfried Leibniz and Christiaan Huygens, "the greatest mathematician in the generation before Newton and Leibniz". It's a cool story: a genius of the old generation learns a paradigm-shifting new discipline via correspondence with a genius of the new generation who is in the process of mapping the discipline.

The "Sounds great, but..." part comes near the end of the article, when the author extrapolates from Huygens's attitude to what is wrong with math education these days. It seems that Huygens wanted to see connections between the crazy new operations he was learning, including second derivatives, and the real world. Without seeing these connections, he wasn't as motivated to put in the effort to learn them.

The author then asserts:

The point is not that mathematics needs to be applied. It is that it needs to be motivated. We don't study nature because we refuse to admit value in abstract mathematics. We study nature because she has repeatedly proven herself to have excellent mathematical taste, which is more than can be said for the run-of-the-mill mathematicians who have to invent technical pseudo-problems because they can't solve any real ones.

Yikes, that got ugly fast. And it gets uglier, with the author eventually worrying that we alienate present-day Huygenses with a mass of boring problems that are disconnected from reality.

I actually love the heart of that paragraph: We don't study nature because we refuse to admit value in abstract mathematics. We study nature because she has repeatedly proven herself to have excellent mathematical taste.... This is a reasonable claim, and almost poetic. But the idea that pseudo-problems invented by run-of-the-mill mathematicians are the reason students today aren't motivated to learn calculus or other advanced mathematics seems like a massive overreach.

I'm sympathetic to the author's position. I watched my daughters slog through AP Calculus, solving many abstract problems and many applied problems that had only a thin veneer of reality wrapped around them. As someone who enjoyed puzzles for puzzles' sake, I had enjoyed all of my calculus courses, but it seemed as if my daughters and many of their classmates never felt the sort of motivation that Huygens craved and Leibniz delivered.

I also see many computer science students slog through courses in which they learn to program, apply computational theory to problems, and study the intricate workings of software and hardware systems. Abstract problems are a fine way to learn how to program, but they don't always motivate students to put in a lot of work on challenging material. However, real problems can be too unruly for many settings, though, so simplified, abstract problems are common.

But it's not quite as easy to fix this problem by saying "learn calculus like Huygens: solve real problems!". There are a number of impediments to this being a straightforward solution in practice.

One is the need for domain knowledge. Few, if any, of the students sitting in today's calculus classes have much in common with Huygens, a brilliant natural scientist and inventor who had spent his life investigating hard problems. He brought a wealth of knowledge to his study of mathematics. I'm guessing that Leibniz didn't have to search long to find applications with which Huygens was already familiar and whose solutions he cared about.

Maybe in the old days all math students were learning a lot of science at the same time as they learned math, but that is not always so now. In order to motivate students with real problems, you need real problems from many domains, in hopes of hitting all students' backgrounds and interests. Even then, you may not cover them all. And, even if you do, you need lots of problems for them to practice on.

I think about these problems every day from the perspective of a computer science prof, and I think there are a lot of parallels between motivating math students and motivating CS students. How do I give my students problems from domains they both know something about and are curious enough to learn more about? How do I do that in a room with thirty-five students with as many different backgrounds? How do I do that in the amount of time I have to develop and extend my course?

Switching to a computer science perspective brings to mind a second impediment to the "solve real problems" mantra. CS education research offers some evidence that using context-laden problems, even from familiar contexts, can make it more difficult for students to solve programming problems. The authors of the linked paper say:

Our results suggest that any advantage conveyed by a familiar context is dominated by other factors, such as the complexity of terminology used in the description, the length of the problem description, and the availability of examples. This suggests that educators should focus on simplicity of language and the development of examples, rather than seeking contexts that may aid in understanding problems.

Using familiar problems to learn new techniques may help motivate students initially, but that may come at other costs. Complexity and confusion can be demotivating.

So, "learn calculus like Huygens" sounds great, but it's not quite so easy to implement in practice. After many years designing and teaching courses, I have a lot of sympathy for the writers of calculus and intro programming textbooks. I also don't think it gets much easier as students advance through the curriculum. Some students are motivated no matter what the instructor does; others need help. The tension between motivation and the hard work needed to master new techniques is always there. Claims that the tension is easy to resolve are usually too glib to be helpful.

The Huygens-Leibniz tale really is a cool story, though. You might enjoy it.

(The image above is a sketch of Christiaan Huygens's first pendulum clock, from 1657. Source: Wikipedia.)

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

April 06, 2018 3:19 PM

Maps and Abstractions

I've been reading my way through Frank Chimero's talks online and ran across a great bit on maps and interaction design in What Screens Want. One of the paragraphs made me think about the abstractions that show up in CS courses:

When I realized that, a little light went off in my head: a map's biases do service to one need, but distort everything else. Meaning, they misinform and confuse those with different needs.

CS courses are full of abstractions and models of complex systems. We use examples, often simplified, to expose or emphasize a single facet a system, as a way to help students cut through the complexity. For example, compilers and full-strength interpreters are complicated programs, so we start with simple interpreters operating over simple languages. Students get their feet wet without drowning in detail.

In the service of trying not to overwhelm students, though, we run the risk of distorting how they think about the parts we left out. Worse, we sometimes distort even their thinking about the part we're focusing on, because they don't see its connections to the more complete picture. There is an art to identifying abstractions, creating examples, and sequencing instruction. Done well, we can minimize the distortions and help students come to understand the whole with small steps and incremental increases in size and complexity.

At least that's what I think on my good days. There are days and even entire semesters when things don't seem to progress as smoothly as I hope or as smoothly as past experience has led me to expect. Those days, I feel like I'm doing violence to an idea when I create an abstraction or adopt a simplifying assumption. Students don't seem to be grokking the terrain, so change the map. We try different problems or work through more examples. It's hard to find the balance sometimes between adding enough to help and not adding so much as to overwhelm.

The best teachers I've encountered know how to approach this challenge. More importantly, they seem to enjoy the challenge. I'm guessing that teachers who don't enjoy it must be frustrated a lot. I enjoy it, and even so there are times when this challenge frustrates me.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 23, 2018 3:45 PM

A New Way to Design Programming Languages?

Greg Wilson wrote a short blog post recently about why JavaScript isn't suitable for teaching Data Carpentry-style workshops. In closing, he suggests an unusual way to design programming languages:

What I do know is that the world would be a better place if language designers adopted tutorial-driven design: write the lessons that introduce newcomers to the language, then implement the features those tutorials require.

That's a different sort of TDD than I'm used to...

This is the sort of idea that causes me to do a double or triple take. At first, it has an appealing ring to it, when considering how difficult it is to teach most programming languages to novices. Then I think a bit and decide that it sounds crazy because, really, are we going to hamstring our languages by focusing on the struggles of beginners? But then it sits in my mind for a while and I start to wonder if we couldn't grow a decent language this way. It's almost like using the old TDD to implement new the TDD.

The PLT Scheme folks have designed a set of teaching languages that enable beginners to grow into an industry-strength language. That design project seems to have worked from the outsides in, with a target language in mind while designing the teaching languages. Maybe Wilson's idea of starting at the beginning isn't so crazy after all.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

March 22, 2018 4:05 PM

Finally, Some Good News

It's been a tough semester. On top of the usual business, there have been a couple of extra stresses. First, I've been preparing for the departure of a very good friend, who is leaving the university and the area for family and personal reasons. Second, a good friend and department colleague took an unexpected leave that turned into a resignation. Both departures cast a distant pall over my workdays. This week, though, has offered a few positive notes to offset the sadness.

Everyone seems to complain about email these days, and I certainly have been receiving and sending more than usual this semester, as our students and I adjust to the change in our faculty. But sometimes an email message makes my day better. Exhibit 1, a message from a student dealing with a specific issue:

Thank you for your quick and helpful response!
Things don't look so complicated or hopeless now.

Exhibit 2, a message from a student who has been taming the bureaucracy that arises whenever two university systems collide:

I would like to thank you dearly for your prompt and thorough responses to my numerous emails. Every time I come to you with a question, I feel as though I am receiving the amount of respect and attention that I wish to be given.

Compliments like these make it a lot easier to muster the energy to deal with the next batch of email coming in.

There has also been good news on the student front. I received email from a rep at a company in Madison, Wisconsin, where one of our alumni works. They are looking for developers to work in a functional programming environment and are having a hard time filling the positions locally, despite the presence of a large and excellent university in town. Our alum is doing well enough that the company would like to hire more from our department, which is doing a pretty good job, too.

Finally, today I spoke in person with two students who had great news about their futures. One has accepted an offer to join the Northwestern U. doctoral program and work in the lab of Kenneth Forbus. I studied Forbus's work on qualitative reasoning and analogical reasoning as a part of my own Ph.D. work and learned a lot from him. This is a fantastic opportunity. The other student has accepted an internship to work at PlayStation this summer, working on the team that develops the compilers for its game engines. He told me, "I talked a lot about the project I did in your course last semester during my interview, and I assume that's part of the reason I got an offer." I have to admit, that made me smile.

I had both of these students in my intro class a few years back. They would have succeeded no matter who taught their intro course, or the compiler course, for that matter, so I can't take any credit for their success. But they are outstanding young men, and I have had the pleasure of getting to know over the last four years. News of the next steps in their careers makes me feel good, too.

I think I have enough energy to make it to the end of the semester now.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

March 12, 2018 3:43 PM

Technology is a Place Where We Live

Yesterday morning I read The Good Room, a talk Frank Chimero gave last month. Early on in the talk, Chimero says:

Let me start by stating something obvious: in the last decade, technology has transformed from a tool that we use to a place where we live.

This sentence jumped off the page both for the content of the assertion and for the decade time frame with which he bounds it. In the fall of 2003, I taught a capstone course for non-majors that is part of my university's liberal arts core. The course, titled "Environment, Technology, and Society", brings students from all majors on campus together in a course near the end of their studies, to apply their general education and various disciplinary expertises to problems of some currency in the world. As you might guess from the title, the course focuses on problems at the intersection of the natural environment, technology, and people.

My offering of the course put on a twist on the usual course content. We focused on the man-made environment we all live in, which even by 2003 had begun to include spaces carved out on the internet and web. The only textbook for the course was Donald Norman's The Design of Everyday Things, which I think every university graduate should have read. The topics for the course, though, had a decided IT flavor: the effect of the Internet on everyday life, e-commerce, spam, intellectual property, software warranties, sociable robots, AI in law and medicine, privacy, and free software. We closed with a discussion of what an educated citizen of the 21st century ought to know about the online world in which they would live in order to prosper as individuals and as a society.

The change in topic didn't excite everyone. A few came to the course looking forward to a comfortable "save the environment" vibe and were resistant to considering technology they didn't understand. But most were taking the course with no intellectual investment at all, as a required general education course they didn't care about and just needed to check off the list. In a strange way, their resignation enabled them to engage with the new ideas and actually ask some interesting questions about their future.

Looking back now after fifteen years , the course design looks pretty good. I should probably offer to teach it again, updated appropriately, of course, and see where young people of 2018 see themselves in the technological world. As Chimero argues in his talk, we need to do a better job building the places we want to live in -- and that we want our children to live in. Privacy, online peer pressure, and bullying all turned out differently than I expected in 2003. Our young people are worse off for those differences, though I think most have learned ways to live online in spite of the bad neighborhoods. Maybe they can help us build better places to live.

Chimero's talk is educational, entertaining, and quotable throughout. I tweeted one quote: "How does a city wish to be? Look to the library. A library is the gift a city gives to itself." There were many other lines I marked for myself, including:

  • Penn Station "resembles what Kafka would write about if he had the chance to see a derelict shopping mall." (I'm a big Kafka fan.)
  • "The wrong roads are being paved in an increasingly automated culture that values ease."
Check the talk out for yourself.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

February 12, 2018 4:03 PM

How Do We Choose The Programming Languages We Love?

In Material as Metaphor, the artist Anni Albers talks about how she came to choose media in which she worked:

How do we choose our specific material, our means of communication? "Accidentally". Something speaks to us, a sound, a touch, hardness or softness, it catches us and asks us to be formed. We are finding our language, and as we go along we learn to obey their rules and their limits. We have to obey, and adjust to those demands. Ideas flow from it to us and though we feel to be the creator we are involved in a dialogue with our medium. The more subtly we are tuned to our medium, the more inventive our actions will become. Not listening to it ends in failure.

This expresses much the way I feel about different programming languages and styles. I can like them all, and sometimes do! I go through phases when one style speaks to me more than another, or when one language seems to be in sync with how I am thinking. When that happens, I find myself wanting to learn its rules, to conform so that I can reach a point where I feel creative enough to solve interesting problems in the language.

If I find myself not liking a language, it's usually because I'm not listening to it; I'm fighting back. When I first tried to learn Haskell, I refused to bend to its style of functional programming. I had worked hard to grok FP in Scheme, and I was so proud of my hard-won understanding that I wanted to impose it on the new language. Eventually, I retreated for a while, returned more humbly, and finally came to appreciate Haskell, if not master it deeply.

My experience with Smalltalk went differently. One summer I listened to what it was telling me, slowly and patiently, throwing code away and starting over several times on an application I was trying to build. This didn't feel like a struggle so much as a several-month tutoring session. By the end, I felt ideas flowing through me. I think that's the kind of dialogue Albers is referring to.

If I want to master a new programming language, I have to be willing to obey its limits and to learn how to use its strengths as leverage. This can be a conscious choice. It's frustrating when that doesn't seem to be enough.

I wish I could always will myself into the right frame of mind to learn a new way of thinking. Albers reminds us that often a language speaks to us first. Sometimes, I just have to walk away and wait until the time is right.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Software Development, Teaching and Learning

January 17, 2018 3:51 PM


While discussing the effective use of discontinuities in film, both motion within a context versus change of context, Walter Murch tells a story about... bees:

A beehive can apparently be moved two inches each night without disorienting the bees the next morning. Surprisingly, if it is moved two miles, the bees also have no problem: They are forced by the total displacement of their environment to re-orient their sense of direction, which they can do easily enough. But if the hive is moved two yards, the bees become fatally confused. The environment does not seem different to them, so they do not re-orient themselves, and as a result, they will not recognize their own hive when they return from foraging, hovering instead in the empty space where the hive used to be, while the hive itself sits just two yards away.

This is fascinating, as well being a really cool analogy for the choices movies editors face when telling a story on film. Either change so little that viewers recognize the motion as natural, or change enough that they re-orient their perspective. Don't stop in the middle.

What is even cooler to me is that this story appears in a footnote.

One of the things I've been loving about In the Blink of an Eye is how Murch uses footnotes to teach. In many books, footnotes contain minutia or references to literature I'll never read, so I skip them. But Murch uses them to tell stories that elaborate on or deepen his main point but which would, if included in the text, interrupt the flow of the story he has constructed. They add to the narrative without being essential.

I've already learned a couple of cool things from his footnotes, and I'm not even a quarter of the way into the book. (I've been taking time to mull over what I read...) Another example: while discussing the value of discontinuity as a story-telling device, Murch adds a footnote that connects this practice to the visual discontinuity found ancient Egyptian painting. I never knew before why the perspective in those drawings was so unusual. Now I do!

My fondness for Murch's footnotes may stem from something more than their informative nature. When writing up lecture notes for my students, I like to include asides, digressions, and links to optional readings that expand on the main arc of the story. I'd like for them to realize that what they are learning is part of a world bigger than our course, that the ideas are often deeper and have wider implications than they might realize. And sometimes I just like to entertain with a connection. Not all students care about this material, but for the ones who do, I hope they get something out of them. Students who don't care can do what I do in other books: skip 'em.

This book gives me a higher goal to shoot for when including such asides in my notes: elaborate without being essential; entice without disrupting.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

January 15, 2018 9:22 AM

The Cut

Walter Murch, in In the Blink of an Eye:

A vast amount of preparation, really, to arrive at the innocuously brief moment of decisive act: the cut -- the moment of transition from one shot to the next -- something that, appropriately enough, should look almost self-evidently simple and effortless, if it is even noticed at all.

This can apply to software development, I think, but I haven't thought about that yet. I read the passage at the beginning of a new semester, when my mind is filled with another offering of my programming languages course. So I've been thinking about how this quote works in the context of my course: the overall structure of the course as well as the structure of individual class sessions. The course consists of three major units, connected by a thread, with the third having its own substructure. Each session is a more cohesive story with its own microstructure: the flow of a lecture, the sequence of exercises students do, the sequence of examples that students see. Moments of transition are everywhere, at multiple scales.

When a session goes badly, or not as well as I'd hoped, I am quite aware of the cuts that did not work. They seem awkward, or ill-motivated, or jarring. The students notice some of these, too, but they don't always let me know of their disorientation right away. That's one benefit of building frequent exercises and review questions into a class session: at least I have a chance of finding out sooner when something isn't working the way I'd planned.

Reading Murch has given me a new vocabulary for thinking about transitions visually. In particular, I've been thinking about two basic types of transition:

  • one that signals motion within a context
  • one that signals a change of context
These are a natural part of any writer's job, but I've found it helpful to think about them more explicitly as I worked on class this week.

Charlie Brown's teacher drones on

For example, I've been trying to think more often about how one kind of cut can be mistaken for the other and how that might affect students. What happens when what I intend as a small move within a context seems so disconnected for students that they think I've changed contexts? What happens when what I intend as a big shift to a new topic sounds to students like the WAH-WAH-WAH of Charlie Brown's teacher? I can always erect massive signposts to signal transitions of various kinds, but that can be just as jarring to readers or listeners as unannounced cuts. It is also inelegant, because it fails to respect their ability to construct their own understanding of what they are learning.

Trying on Murch's perspective has not been a panacea. The first session of the course, the one with a new opening story, went well, though it needs a few more iterations to become good. My second session went less well. I tried to rearrange a session that already worked well, and my thinking about transitions was too self-conscious. The result was a synthesis of two threads that didn't quite work, leaving me feeling a bit jumbled myself by connections that were incomplete and jumps that seemed abrupt. Fortunately, I think I managed to recognize this soon enough in class that I was able to tell a more coherent story than my outline prepared me to tell. The outline needs a lot more work.

In the longer run, though, thinking about transitions more carefully should help me do a better job leading students in a fruitful direction. I'll keep at it.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

January 14, 2018 9:24 AM


This was posted on the Racket mailing list recently:

"The Little Schemer" starts slow for people who have programmed before, but seeing that I am only half-way through and already gained some interesting knowledge from it, one should not underestimate the acceleration in this book.

The Little Schemer is the only textbook I assign in my Programming Languages course. These students usually have only a little experience: often three semesters, two in Python and one in Java; sometimes just the two in Python. A few of the students who work in the way the authors intend have an A-ha! experience while reading it. Or maybe they are just lucky... Other students have only a WTF? experience.

Still, I assign the book, with hope. It's relatively inexpensive and so worth a chance that a few students can use it to grok recursion, along with a way of thinking about writing functions that they haven't seen in courses or textbooks before. The book accelerates from the most basic ideas of programming to "interesting" knowledge in a relatively short number of pages. Students who buy in to the premise, hang on for the ride, and practice the ideas in their own code soon find that they, too, have accelerated as programmers.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 07, 2018 10:25 AM


This morning, I read the first few pages of In the Blink of an Eye, an essay on film editing by Walter Murch. He starts by talking about his work on Apocalypse Now, which took well over a year in large part because of the massive amount of film Coppola shot: 1,250,000 linear feet, enough for 230 hours of running time. The movie ended up being about two hours and twenty-five minutes, so Murch and his colleagues culled 95 minutes of footage for every minute that made it into the final product. A more typical project, Murch says, has a ratio of 20:1.

Even at 20:1, Murch's story puts into clearer light the amount of raw material I create when designing a typical session for one of my courses. The typical session mixes exposition, examples, student exercises, and (less than I'd like to admit) discussion. Now, whenever I feel like a session comes up short of my goal, I will think back on Murch's 20:1 ratio and realize how much harder I might work to produce enough material to assemble a good session. If I want one of my sessions to be an Apocalypse Now, maybe I'll need to shoot higher.

This motivation comes at a favorable time. Yesterday I had a burst of what felt like inspiration for a new first day to my Programming Languages course. At the end of the brainstorm came what is now the working version of my opening line in the course: "In the beginning, there was assembly language.". Let's see if I have enough inspiration -- and make enough time -- to turn the idea into what I hope it can be: a session that fuels my students' imagination for a semester's journey through Racket, functional programming, and examining language ideas with interpreters.

I do hope, though, that the journey itself does not bring to mind Apocalypse Now.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

January 05, 2018 1:27 PM

Change of Terms

I received a Change of Terms message yesterday from one of my mutual fund companies, which included this unexpected note:

Direction to buy or sell Vanguard funds must be placed online or verbally and may no longer be submitted in writing.

I haven't mailed Vanguard or any other financial services company a paper form or a paper check in years, but still. When I was growing up, I never would have imagined that I would see the day when you could not mail a letter to a company in order to conduct financial business. Busy, busy, busy.

In the academic world, this is the time for another type change of terms, as we prepare to launch our spring semester semester on Monday. The temperatures in my part of the country the last two weeks make the name of the semester a cruel joke, but the hope of spring lives.

For me, the transition is from my compiler course to my programming languages course. Compilers went as well this fall as it has gone in a long time; I really wish I had blogged about it more. I can only hope that Programming Languages goes as well. I've been reading about some ways I might improve the course pedagogically. That will require me to change some old habits, but trying to do so is part of the fun of teaching. I intend to blog about my experiences with the new ideas. As I said, the hope of spring lives.

In any case, I get to write Racket code all semester, so at least I have that going for me, which is nice.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

December 28, 2017 8:46 AM

You Have to Learn That It's All Beautiful

In this interview with Adam Grant, Walter Jacobson talks about some of the things he learned while writing biographies of Benjamin Franklin, Albert Einstein, Steve Jobs, and Leonardo da Vinci. A common theme is that all four were curious and interested in a wide range of topics. Toward the end of the interview, Jacobson says:

We of humanities backgrounds are always doing the lecture, like, "We need to put the 'A' in 'STEM', and you've got to learn the arts and the humanities." And you get big applause when you talk about the importance of that.

But we also have to meet halfway and learn the beauty of math. Because people tell me, "I can't believe somebody doesn't know the difference between Mozart and Haydn, or the difference between Lear and Macbeth." And I say, "Yeah, but do you know the difference between a resistor and a transistor? Do you know the difference between an integral and a differential equation?" They go, "Oh no, I don't do math, I don't do science." I say, "Yeah, but you know what, an integral equation is just as beautiful as a brush stroke on the Mona Lisa." You've got to learn that they're all beautiful.

Appreciating that beauty made Leonardo a better artist and Jobs a better technologist. I would like for the students who graduate from our CS program to know some literature, history, and art and appreciate their beauty. I'd also like for the students who graduate from our university with degrees in literature, history, art, and especially education to have some knowledge of calculus, the Turing machine, and recombinant DNA, and appreciate their beauty.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

December 22, 2017 12:50 PM

The Power of an App or a Sideways Glance

This morning I read an interview with Steven Soderbergh, which is mostly about his latest project, the app/series, "Mosaic". A few weeks ago, "Mosaic" was released as an app in advance of its debut on HBO. Actually, that's not quite right. It is an app, which will also be released later in series form, and then only because Soderbergh needed money to finish the app version of the film. In several places, he talks about being a director in ways that made me think of being a university professor these days.

One was in terms of technology. There are moments in the "Mosaic" app when it offers the viewer an opportunity to digress and read a document, to flash back, or to flash forward. The interviewer is intrigued by the notion that a filmmaker would be willing to distract the viewer in this way, sending texts and pushing notifications that might disrupt the experience. Soderbergh responded:

My attitude was, "Look, we've gotten used to watching TV now with three scrolling lines of information at the bottom of the screen all the time. People do not view that stuff the same way that they would have viewed it 20 years ago."

... To not acknowledge that when you're watching something on your phone or iPad that there are other things going on around you is to be in denial. My attitude is, "Well, if they're going to be distracted by something, let it be me!"

I'm beginning to wonder if this wouldn't be a healthier attitude for us to have as university instructors. Maybe I should create an app that is my course and let students experience the material using what is, for them, a native mode of interaction? Eventually they'll have to sit down and do the hard work of solving problems and writing code, but they could come to that work in a different way. There is a lot of value in our traditional modes of teaching and learning, but maybe flowing into our students' daily experience with push requests and teaser posts would reach them in a different way.

Alas, I doubt that HBO will front me any money to make my app, so I'll have to seem other sources of financing.

On a more personal plane, I was struck by something that Soderbergh said about the power directors have over the people they work with:

What's also interesting, given the environment we're in right now, is that I typically spend the last quarter of whatever talk I'm giving [to future fillmakers] discussing personal character, how to behave, and why there should be some accepted standard of behavior when you interact with people and how you treat people. Particularly when you're in a position like that of a director, which is an incredibly powerful situation to be in, pregnant with all kinds of opportunity to be abusive.

... if you're in a position of power, you can look at somebody sideways and destroy their week, you know? You need to be sensitive to the kind of power that a director has on a set.

It took me years as a teacher to realize the effect that an offhand remark could have on a student. I could be lecturing in class, or chatting with someone in my office, and say something about the course, or about how I work, or about how students work or think. This sentence, a small part of a larger story, might not mean all that much to me, and yet I would learn later that it affected how the student felt about himself or herself for a week, or for the rest of the course, or even longer. This effect can be positive or negative, of course, depending on the nature of the remark. As Soderbergh says, it's worth thinking about how you behave when you interact with people, especially when you're in a position of relative authority, in particular as a teacher working with young people.

This applies to our time as a parent and a spouse, too. Some of my most regrettable memories over the years are of moments in which I made an offhand remark, thoughtlessly careless, that cut deep into the heart of my wife or one of my daughters. Years later, they rarely remember the moment or the remark, but I'm sad for the pain I caused in that moment and for any lingering effect it may have. The memory is hard for me to shake. I have to hope that the good things I have said and done during our time together meant as much. I can also try to do better now. The same holds true for my time working with students.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

December 20, 2017 3:51 PM

== false

While grading one last project for the semester, I ran across this gem:

    if checkInputParameters() == False:

This code was not written by a beginning programmer, but a senior who likely will graduate in May. Sigh.

I inherited this course late in the semester, so it would be nice if I could absolve myself of responsibility for allowing a student to develop such a bad habit. But this isn't the first time I've seen this programming pattern. I've seen it in my courses and in other faculty's courses, in first-year courses and fourth-year courses. In fact, I was so certain that I blogged about the pattern before that I spent several minutes trolling the archive. Alas, I never found the entry.

Don't let anyone tell you that Twitter can't be helpful. Within minutes of tweeting my dismay, two colleagues suggested new strategies for dealing with this anti-pattern.

Sylvain Leroux invoked Star Trek:

James T. Kirk "Kobayashi Maru"-style solution: Hack CPython to properly parse that new syntax:

unless checkInputParameters(): ...

Maybe I'll turn this into a programming exercise for the next student in my compiler class who wanders down the path of temptation. Deep in my heart, though, I know that enterprising programmers will use the new type of statement to write this:

    unless checkInputParameters() == True:

Agile Hulk suggested a fix:

    if (checkInputParameters() == False) == True:

This might actually be a productive pedagogical tack to follow: light-hearted and spot on, highlighting the anti-pattern's flaw by applying it to its own output. ("Anti-pattern eats its own dog food.") With any luck, some students will be enlightened, Zen-like. Others will furrow their brow and say "What?"

... and even if we look past the boolean crime in our featured code snippet, we really ought to take on that function name. 'Tis the season, though, and the semester is over. I'll save that rant for another time.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

November 14, 2017 3:52 PM

Thinking about Next Semester's Course Already

We are deep into fall semester. The three teams in my compilers course are making steady progress toward a working compiler, and I'm getting so excited by that prospect that I've written a few new programs for them to compile. The latest two work with Kaprekar numbers.

Yet I've also found myself thinking already quite a bit about my spring programming languages course.

I have not made significant changes to this course (which introduces students to Racket, functional programming, recursive programming over algebraic data types, and a few principles of programming languages) in several years. I don't know if I'm headed for a major re-design yet, but I do know that several new ideas are commingling in my mind and encouraging me to think about improvements to the course.

The first trigger was reading How to Switch from the Imperative Mindset, which approaches learning functional style explicitly as a matter establishing new habits. My students come to the course having learned an imperative style in Python, perhaps with some OO in Java thrown in. Most of them are not yet 100% secure in their programming skills, and the thought of learning a new style is daunting. They don't come to the course asking for a new set of habits.

One way to develop a new set of habits is to recognize the cues that trigger an old habit, learn a new response, and then rehearse that response until it becomes a new habit. The How to Switch... post echoes a style that I have found effective when teaching OOP to programmers with experience in a procedural language, and I'm thinking about how to re-tool part of my course to use this style more explicitly when teaching FP.

My idea right now is something like this. Start with simple examples from the students' experience processing arrays and lists of data. Then work through solutions in sequence, such as:

  1. first, use a loop of the sort with which they are familiar, the body of which acts on each item in the collection
  2. then, move the action into a function, which the loop calls for each item in the collection
  3. finally, map the function over the items in the collection

We can also do this with built-in functions, perhaps to start, which eliminates the need to write a user-defined function.

In effect, this refactors code that the students are already comfortable with toward common functional patterns. I can use the same sequence of steps for mapping, folding, and reducing, which will reinforce the thinking habits students need to begin writing FP code from the original cues. I'm only just beginning to think about this approach, but I'm quite comfortable using a "refactoring to patterns" style in class.

Going in this direction will help me achieve another goal I have in mind for next semester: making class sessions more active. This was triggered by my post-mortem of the last course offering. Some early parts of the course consist of too much lecture. I want to get students writing small bits of code sooner, but with more support for taking small, reliable steps.

Paired this change to what happens in class are changes to what happens before students come to class. Rather than me talking about so many things in class, I hope to have

  • students reading clear expositions of the material, in small units that are followed immediately by
  • students doing more experimentation on their own in Dr. Racket, learning from the experiments and learning find information about language features as they need them.

This change will require me to package my notes differently and also to create triggers and scaffolding for the students' experimentation before coming to class. I'm thinking of this as something like a flipped classroom, but with "watching videos" replaced by "playing with code".

Finally, this blog post triggered a latent desire to make the course more effective for all students, wherever they are on the learning curve. Many students come to the course at roughly same level of experience and comfort, but a few come in struggling from their previous courses, and a few come in ready to take on bigger challenges. Even those broad categories are only approximate equivalence classes; each student is at a particular point in the development we hope for them. I'd like to create experiences that can help students all of these students learn something valuable for them.

I've only begun to think about the ideas in that post. Right now, I'm contemplating two of ideas from the section on getting to know my students better: gathering baseline data early on that I can use to anchor the course, and viewing grading as planning. Anything that can turn the drudgery of grading into a productive part of the course for me is likely to improve my experience in the course, and that is likely to improved my students' experience, too.

I have more questions than answers at this point. That's part of the fun of re-designing a course. I expect that things will take better shape over the next six weeks or so. If you have any suggestions, email me or tweet to me at @wallingf.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Teaching and Learning

October 03, 2017 12:23 PM

Why Do CS Enrollments Surges End?

The opening talk of the CS Education Summit this week considered the challenges facing CS education in a time of surging enrollments and continued concerns about the diversity of the CS student population. In the session that followed, Eric Roberts and Jodi Tims presented data that puts the current enrollment surge into perspective, in advance of a report from the National Academy of Science.

In terms of immediate takeaway, Eric Roberts's comments were gold. Eric opened with Stein's Law: If something is unsustainable, it will stop. Stein was an economist whose eponymous law expresses one of those obvious truths we all seem to forget about in periods of rapid change: If something cannot go on forever, it won't. You don't have to create a program to make it stop. A natural corollary is: If it can't go on for long, you don't need a program to deal with it. It will pass soon.

Why is that relevant to the summit? Even without continued growth, current enrollments in CS majors is unsustainable for many schools. If the past is any guide, we know that many schools will deal with unsustainable growth by limiting the number of students who start or remain in their major.

Roberts has studied the history of CS boom-and-bust cycles over the last thirty years, and he's identified a few common patterns:

  • Limiting enrollments is how departments respond to enrollment growth. They must: the big schools can't hire faculty fast enough, and most small schools can't hire new faculty at all.

  • The number of students graduating with CS degrees drops because we limit enrollments. Students do not stop enrolling because the number of job opportunities goes down or any other cause.

    After the dot-com bust, there was a lot of talk about offshoring and automation, but the effects of that were short-term and rather small. Roberts's data shows that enrollment crashes do not follow crashes in job openings; they follow enrollment caps. Enrollments remain strong wherever they are not strictly limited.

  • When we limit enrollments, the effect is bigger on women and members of underserved communities. These students are more likely to suffer from impostor syndrome, stereotype bias, and other fears, and the increased competitiveness among students for fewer openings combines with discourages them from continuing.

So the challenge of booming enrollments exacerbates the challenge to increase diversity. The boom might decrease diversity, but when it ends -- and it will, if we limit enrollments -- our diversity rarely recovers. That's the story of the last three booms.

In order to grow capacity, the most immediate solution is to hire more professors. I hope to write more about that soon, but for now I'll mention only that the problem of hiring enough faculty to teach all of our students has at east two facets. The first is that many schools simply don't have the money to hire more faculty right now. The second is that there aren't enough CS PhDs to go around. Roberts reported that, of last year's PhD grads, 83% took positions at R1 schools. That leaves 17% for the rest of us. "Non-R1 schools can expect to hire a CS PhD every 27 years." Everyone laughed, but I could see anxiety on more than a few faces.

The value of knowing this history is that, when we go to our deans and provosts, we can do more than argue for more resources. We can show the effect of not providing the resources needed to teach all the students coming our way. We won't just be putting the brakes on local growth; we may be helping to create the next enrollment crash. At a school like mine, if we teach the people of our state that we can't handle their CS students, then the people of our state will send their students elsewhere.

The problem for any one university, of course, is that it can act only based on its own resources and under local constraints. My dean and provost might care a lot about the global issues of demand for CS grads and need for greater diversity among CS students. But their job is to address local issues with their own (small) pool of money.

I'll have to re-read the papers Roberts has written about this topic. His remarks certainly gave us plenty to think about, and he was as engaging as ever.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

October 02, 2017 12:16 PM

The Challenge Facing CS Education

Today and tomorrow, I am at a CS Education Summit in Pittsburgh. I've only been to Pittsburgh once before, for ICFP 2002 (the International Conference on Functional Programming) and am glad to be back. It's a neat city.

The welcome address for the summit was given by Dr. Farnam Jahanian, the interim president at Carnegie Mellon University. Jahanian is a computer scientist, with a background in distributed computing and network security. His resume includes a stint as chair of the CS department at the University of Michigan and a stint at the NSF.

Welcome addresses for conferences and workshops vary in quality. Jahanian gave quite a good talk, putting the work of the summit into historical and cultural context. The current boom in CS enrollments is happening at a time when computing, broadly defined, is having an effect in seemingly all disciplines and all sectors of the economy. What does that mean for how we respond to the growth? Will we see that the current boom presages a change to the historical cycle of enrollments in coming years?

Jahanian made three statements in particular that for me capture the challenge facing CS departments everywhere and serve as a backdrop for the summit:

  • "We have to figure out how to teach all of these students."

    Unlike many past enrollment booms, "all of these students" this time comprises two very different subsets: CS majors and non-majors. We have plenty of experience teaching CS majors, but how do you structure your curriculum and classes when you have three times as many majors? When numbers go up far enough fast enough, many schools have a qualitatively different problem.

    Most departments have far less experience teaching computer science (not "literacy") to non-majors. How do you teach all of these students, with different backgrounds and expectations and needs? What do you teach them?

  • "This is an enormous responsibility."

    Today's graduates will have careers for 45 years or more. That's a long time, especially in a world that is changing ever more rapidly, in large part due to our own discipline. How different are the long-term needs of CS majors and non-majors? Both groups will be working and living for a long time after they graduate. If computing remains a central feature of the world in the future, how we respond to enrollment growth now will have an outsized effect on every graduate. An enormous responsibility, indeed.

  • "We in CS have to think about impending cultural changes..."

    ... which means that we computer science folks will need to have education, knowledge, and interests much broader than just CS. People talk all the time about the value of the humanities in undergraduate education. This is a great example of why. One bit of good news: as near as I can tell, most of the CS faculty in this room, at this summit, do have interests and education bigger than just computer science (*). But we have to find ways to work these issues into our classrooms, with both majors and non-majors.

Thus the idea of a CS education summit. I'm glad to be here.

(*) In my experience, it is much more likely to find a person with a CS or math PhD and significant educational background in the humanities than to find a person with a humanities PhD and significant educational background in CS or math (or any other science, for that matter). One of my hopes for the current trend of increasing interest in CS among non-CS majors is that we an close this gap. All of the departments on our campuses, and thus all of our university graduates, will be better for it.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

September 26, 2017 3:58 PM

Learn Exceptions Later

Yesterday, I mentioned rewriting the rules for computing FIRST and FOLLOW sets using only "plain English". As I was refactoring my descriptions, I realized that one of the reasons students have difficulty with many textbook treatments of the algorithms is that the books give complete and correct definitions of the sets upfront. The presence of X := ε rules complicates the construction of both sets, but they are unnecessary to understanding the commonsense ideas that motivate the sets. Trying to deal with ε too soon can interfere with the students learning what they need to learn in order to eventually understand ε!

When I left the ε rules out of my descriptions, I ended up with what I thought were an approachable set of rules:

  • The FIRST set of a terminal contains only the terminal itself.

  • To compute FIRST for a non-terminal X, find all of the grammar rules that have X on the lefthand side. Add to FIRST(X) all of the items in the FIRST set of the first symbol of each righthand side.

  • The FOLLOW set of the start symbol contains the end-of-stream marker.

  • To compute FOLLOW for a non-terminal X, find all of the grammar rules that have X on the righthand side. If X is followed by a symbol in the rule, add to FOLLOW(X) all of the items in the FIRST set of that symbol. If X is the last symbol in the rule, add to FOLLOW(X) all of the items in the FOLLOW set of the symbol on the rule's lefthand side.

These rules are incomplete, but they have offsetting benefits. Each of these cases is easy to grok with a simple example or two. They also account for a big chunk of the work students need to do in constructing the sets for a typical grammar. As a result, they can get some practice building sets before diving into the gnarlier details ε, which affects both of the main rules above in a couple of ways.

These seems like a two-fold application of the Concrete, Then Abstract pattern. The first is the standard form: we get to see and work with accessible concrete examples before formalizing the rules in mathematical notation. The second involves the nature of the problem itself. The rules above are the concrete manifestation of FIRST and FOLLOW sets; students can master them before considering the more abstract ε cases. The abstract cases are the ones that benefit most from using formal notation.

I think this is an example of another pattern that works well when teaching. We might call it "Learn Exceptions Later", "Handle Exceptions Later", "Save Exceptions For Later", or even "Treat Exceptions as Exceptions". (Naming things is hard.) It is often possible to learn a substantial portion of an idea without considering exceptions at all, and doing so prepares students for learning the exceptions anyway.

I guess I now have at least one idea for my next PLoP paper.

Ironically, writing this post brings to mind a programming pattern that puts exceptions up top, which I learned during the summer Smalltalk taught me OOP. Instead of writing code like this:

    if normal_case(x) then
       // a bunch
       // of lines
       // of code
       // processing x
you can write:
    if abnormal_case(x) then

// a bunch // of lines // of code // processing x

This idiom brings the exceptional case to the top of the function and dispatches with it immediately. On the other hand, it also makes the normal case the main focus of the function, unindented and clear to the eye. It may look like this idiom violates the "Save Exceptions For Later" pattern, but code of this sort can be a natural outgrowth of following the pattern. First, we implement the function to do its normal business and makes sure that it handles all of the usual cases. Only then do we concern ourselves with the exceptional case, and we build it into the function with minimal disruption to the code.

This pattern has served me well over the years, far beyond Smalltalk.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Software Development, Teaching and Learning

September 25, 2017 3:01 PM

A Few Thoughts on My Compilers Course

I've been meaning to blog about my compilers course for more than a month, but life -- including my compilers course -- have kept me busy. Here are three quick notes to prime the pump.

  • I recently came across Lindsey Kuper's My First Fifteen Compilers and thought again about this unusual approach to a compiler course: one compiler a week, growing last week's compiler with a new feature or capability, until you have a complete system. Long, long-time readers of this blog may remember me writing about this idea once over a decade ago.

    The approach still intrigues me. Kuper says that it was "hugely motivating" to have a working compiler at the end of each week. In the end I always shy away from the approach because (1) I'm not yet willing to adopt for my course the Scheme-enabled micro-transformation model for building a compiler and (2) I haven't figured out how to make it work for a more traditional compiler.

    I'm sure I'll remain intrigued and consider it again in the future. Your suggestions are welcome!

  • Last week, I mentioned on Twitter that I was trying to explain how to compute FIRST and FOLLOW sets using only "plain English". It was hard. Writing a textual description of the process made me appreciate the value of using and understanding mathematical notation. It is so expressive and so concise. The problem for students is that it is also quite imposing until they get it. Before then, the notation can be a roadblock on the way to understanding something at an intuitive level.

    My usual approach in class to FIRST and FOLLOW sets, as for most topics, is to start with an example, reason about it in commonsense terms, and only then to formalize. The commonsense reasoning often helps students understand the formal expression, thus removing some of its bite. It's a variant of the "Concrete, Then Abstract" pattern.

    Mathematical definitions such as these can motivate some students to develop their formal reasoning skills. Many people prefer to let students develop their "mathematical maturity" in math courses, but this is really just an avoidance mechanism. "Let the Math department fail them" may solve a practical problem, sometimes we CS profs have to bite the bullet and help our students get better when they need it.

  • I have been trying to write more code for the course this semester, both for my enjoyment (and sanity) and for use in class. Earlier, I wrote a couple of toy programs such as a Fizzbuzz compiler. This weekend I took a deeper dive and began to implement my students' compiler project in full detail. It was a lot of fun to be deep in the mire of a real program again. I have already learned and re-learned a few things about Python, git, and bash, and I'm only a quarter of the way in! Now I just have to make time to do the rest as the semester moves forward.

In her post, Kuper said that her first compiler course was "a lot of hard work" but "the most fun I'd ever had writing code". I always tell my students that this course will be just like that for them. They are more likely to believe the first claim than the second. Diving in, I'm remembering those feelings firsthand. I think my students will be glad that I dove in. I'm reliving some of the challenges of doing everything that I ask them to do. This is already generating a new source of empathy for my students, which will probably be good for them come grading time.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Software Development, Teaching and Learning

August 26, 2017 12:02 PM

"You Are Here"

a graph relating understanding, writing, and time

This graph illustrates one of the problems that afflicts me as a writer. Too often, I don't have the confidence (or gumption) to start writing until I reach the X. By that time in the learning cycle, downhill momentum is significant. It's easier not to write, either because I figure what I have to say is old news or because my mind has moved on to another topic.

I am thankful that other people share their learning at the top of the curve.


Sarah Perry. created the above image for one of her many fine essays. I came upon it in David Chapman's Ignorant, Irrelevant, and Inscrutable. The blue X is mine.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

August 14, 2017 1:42 PM

Papert 1: Mathophobia, Affect, Physicality, and Love

I have finally started reading Mindstorms. I hope to write short reflections as I complete every few pages or anytime I come across something I feel compelled to write about in the moment. This is the first entry in the imagined series.

In the introduction, Papert says:

We shall see again and again that the consequences of mathophobia go far beyond obstructing the learning of mathematics and science. The interact with other endemic "cultural toxins", for example, with popular theories of aptitudes, to contaminate peoples' images of themselves as learners. Difficulty with school math is often the first step of an invasive intellectual process that leads us all to define ourselves as bundles of aptitudes and ineptitudes, as being "mathematical" or "not mathematical", "artistic" or "not artistic", "musical" or "not musical", "profound" or "superficial", "intelligent" or "dumb". Thus deficiency becomes identity, and learning is transformed from the early child's free exploration of the world to a chore beset by insecurities and self-imposed restrictions.

This invasive intellectual process has often deeply affected potential computer science students long before they reach the university. I would love to see Papert's dream made real early enough that young people can imagine being a computer scientist earlier. It's hard to throw of the shackles after they take hold.


The thing that sticks out as I read the first few pages of Mindstorms is its focus on the power of affect in learning. I don't recall conscious attention to my affect having much of a role in my education; it seems I was in a continual state of "cool, I get to learn something". I didn't realize at the time just what good fortune it was to have that as a default orientation.

I'm also struck by Papert's focus on the role of physicality in learning, how we often learn best when the knowledge has a concrete manifestation in our world. I'll have to think about this more... Looking back now, abstraction always seemed natural to me.

Papert's talk of love -- falling in love with the thing we learn about, but also with the thing we use to learn it -- doesn't surprise me. I know these feelings well, even from the earliest experiences I had in kindergarten.

An outside connection that I will revisit: Frank Oppenheimer's exploratorium, an aspiration I learned about from Alan Kay. What would a computational exploratorium look like?

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

August 11, 2017 9:08 AM

Don't Say "Straightforward" So Often, Obviously

This bullet point from @jessitron's Hyperproductive Development really connected with me:

As the host symbiont who lives and breathes the system: strike the words "just", "easy", "obvious", "simple", and "straightforward" from your vocabulary. These words are contextual, and no other human shares your context.

My first experience coming to grips with my use of these words was not in software development, but in the classroom. "Obvious" has never been a big part of my vocabulary, but I started to notice a few years ago how often I said "just", "easy", and "simple" in class and wrote them in my lecture notes. Since then, I have worked hard to cut back sharply on my uses of these minimizers in both spoken and written interactions with my students. I am not always successful, of course, but I am more aware now and frequently catch myself before speaking, or in the act of writing.

I find that I still use "straightforward" quite often these days. Often, I use it to express contrast explicitly, something to the effect, "This won't necessarily be easy, but at least it's straightforward." By this I mean that some problem or task may require hard work, but at least the steps they need to perform should be clear. I wonder now, though, whether students always take it this way, even when expressed explicitly. Maybe they hear me minimizing the task head, not putting the challenge they face into context.

Used habitually, even with good intentions, a word like "straightforward" can become a crutch, a substitute minimizer. It lets me to be lazy when I try to summarize a process or to encourage students when things get difficult. I'm going to try this fall to be more sensitive to my use of "straightforward" and see if I can't find a better way in most situations.

As for the blog post that prompted this reflection, Hyperproductive Development summarizes as effectively as anything I've read the truth behind the idea that some programmers are so much more effective than others: "it isn't the developers, so much as the situation". It's a good piece, well worth a quick read.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

July 28, 2017 2:02 PM

The Need for Apprenticeship in Software Engineering Education

In his conversation with Tyler Cowen, Ben Sasse talks a bit about how students learn in our schools of public policy, business, and law:

We haven't figured out in most professional schools how to create apprenticeship models where you cycle through different aspects of what doing this kind of work will actually look like. There are ways that there are tighter feedback loops at a med school than there are going to be at a policy school. There are things that I don't think we've thought nearly enough about ways that professional school models should diverge from traditional, theoretical, academic disciplines or humanities, for example.

We see a similar continuum in what works best, and what is needed, for learning computer science and learning software engineering. Computer science education can benefit from the tighter feedback loops and such that apprenticeship provides, but it also has a substantial theoretical component that is suitable for classroom instruction. Learning to be a software engineer requires a shift to the other end of the continuum: we can learn important things, in the classroom, but much of the important the learning happens in the trenches, making things and getting feedback.

A few universities have made big moves in how they structure software engineering instruction, but most have taken only halting steps. They are often held back by a institutional loyalty to the traditional academic model, or out of sheer curricular habit.

The one place you see apprenticeship models in CS is, of course, graduate school. Students who enter research work in the lab under the mentorship of faculty advisors and more senior grad students. It took me a year or so in graduate school to figure out that I needed to begin to place more focus on my research ideas than on my classes. (I hadn't committed to a lab or an advisor yet.)

In lieu of a changed academic model, internships of the sort I mentioned recently can be really helpful for undergrad CS students looking to go into software development. Internships create a weird tension for faculty... Most students come back from the workplace with a new appreciation for the academic knowledge they learn in the classroom, which is good, but they also back to wonder why more of their schoolwork can't have the character of learning in the trenches. They know to want more!

Project-based courses are a way for us to bring the value of apprenticeship to the undergraduate classroom. I am looking forward to building compilers with ten hardy students this fall.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

July 27, 2017 1:36 PM

How can we help students overcome "naturalness bias"?

In Leadership as a Performing Art, Ed Batista discusses, among other things, a "naturalness bias" that humans have when evaluating one another. Naturalness is "a preference for abilities and talents that we perceive as innate over those that appear to derive from effort and experience". Even when people express a preference for hard work and experience, they tend to judge more positively people who seem to be operating on natural skill and talent. As Batista notes, this bias affects not only how we evaluate others but also how we evaluate ourselves.

As I read this article, I could not help but think about how students who are new to programming and to computer science often react to their own struggles in an introductory CS course. These thoughts reached a crescendo when I came to these words:

One commonly-held perspective is that our authentic self is something that exists fully formed within us, and we discover its nature through experiences that feel more (or less) natural to us. We equate authenticity with comfort, and so if something makes us feel uncomfortable or self-conscious, then it is de facto inauthentic, which means we need not persist at it (or are relieved of our responsibility to try). But an alternative view is that our authentic self is something that we create over time, and we play an active role in its development through experiences that may feel uncomfortable or unnatural, particularly at first. As INSEAD professor of organizational behavior Herminia Ibarra wrote in The Authenticity Paradox in 2015,

Because going against our natural inclinations can make us feel like impostors, we tend to latch on to authenticity as an excuse for sticking with what's comfortable... By viewing ourselves as works-in-progress and evolving our professional identities through trial and error, we can develop a personal style that feels right to us and suits our organizations' changing needs. That takes courage, because learning, by definition, starts with unnatural and often superficial behaviors that can make us feel calculating instead of genuine and spontaneous. But the only way to avoid being pigeonholed and ultimately become better leaders is to do the things that a rigidly authentic sense of self would keep us from doing.

So many CS students and even computing professionals report suffering from impostor syndrome, sometimes precisely because they compare their internal struggles to learn with what appears to be the natural ability of their colleagues. But, as Ibarra says, learning, by definition, starts with the unnatural. To be uncomfortable is, in one sense, to be in a position to learn.

How might we teachers of computer science help our students overcome the naturalness bias they unwittingly apply when evaluating their own work and progress? We need strategies to help students see that CS is something we do, not something we are. You can feel uncomfortable and still be authentic.

This distinction is at the foundation of Batista's advice to leaders and, I think, at the foundation of good advice to students. When students can distinguish between their behavior and their identity, they are able to manage more effectively the expectations they have of their own work.

I hope to put what I learned in this article to good use both for my students and myself. It might help me be more honest -- and generous -- to myself when evaluating my performance as a teacher and an administrator, and more deliberate in how I try to get better.

Posted by Eugene Wallingford | Permalink | Categories: General, Managing and Leading, Teaching and Learning

July 21, 2017 3:47 PM

Some Thoughts from a Corporate Visit: Agility and Curriculum

Last Thursday, I spent a day visiting a major IT employer in our state. Their summer interns, at least three of whom are students in my department, were presenting projects they had developed during a three-day codejam. The company invited educators from local universities to come in for the presentations, preceded by a tour of the corporate campus, a meeting with devs who had gone through the internship program in recent years, and a conversation about how the schools and company might collaborate more effectively. Here are a few of my impressions from the visit.

I saw and heard the word "agile" everywhere. The biggest effects of the agility company-wide seemed to be in setting priorities and in providing transparency. The vocabulary consisted mostly of terms from Scrum and kanban. I started to wonder how much the programming practices of XP or other agile methodologies had affected software development practices there. Eventually I heard about the importance of pair programming and unit testing and was happy to know that the developers hadn't been forgotten in the move to agile methods.

Several ideas came to mind during the visit of things we might incorporate into our programs or emphasize more. We do a pretty good job right now, I think. We currently introduce students to agile development extensively in our software engineering course, and we have a dedicated course on software verification and validation. I have even taught a dedicated course on agile software development several times before, most recently in 2014 and 2010. Things we might do better include:

  • having students work on virtual teams. Our students rarely, if ever, work on virtual teams in class, yet this is standard operating procedure even within individual companies these days.

  • having students connect their applications programs to front and back ends. Our students often solve interesting problems with programs, but they don't always have to connect their solution to front ends that engage real users or to back ends that ultimately provide source data. There is a lot to learn in having to address these details.

  • encouraging students to be more comfortable with failure on projects. Schools tends to produce graduates who are risk-averse, because failure on a project in the context of a semester-long course might mean failure in the course. But the simple fact is that some projects fail. Graduates need to be able to learn from failure and create successes out of it. They also need to be willing to take risks; projects with risk are also where big wins come from, not to mention new knowledge.

Over the course of the day, I heard about many of the attributes this company likes to see in candidates for internships and full-time positions, among them:

  • comfort speaking in public
  • ability to handle, accept, and learn from failure
  • curiosity
  • initiative
  • a willingness to work in a wide variety of roles: development, testing, management, etc.
Curiosity was easily the most-mentioned desirable attribute. On the matter of working in a wide variety of roles, even the people with "developer" in their job title reported spending only 30% of their time writing code. One sharp programmer said, "If you're spending 50% of your time writing code, you're doing something wrong."

The codejam presentations themselves were quite impressive. Teams of three to six college students can do some amazing things in three days when they are engaged and when they have the right tools available to them. One theme of the codejam was "platform as a service", and students used a slew of platforms, tools, and libraries to build their apps. Ones that stood out because they were new to me included IBM BlueMix (a l´ AWS and Azure), Twilio ("a cloud platform for building SMS, voice and messaging apps"), and Flask ("a micro web framework written in Python"). I also saw a lot of node.js and lots and lots of NoSQL. There was perhaps a bias toward NoSQL in the tools that the interns wanted to learn, but I wonder if students are losing appreciation for relational DBs and their value.

Each team gave itself a name. This was probably my favorite:

   int erns;
I am a programmer.

All in tools, the interns used too many different tools for me to take note of. That was an important reminder from the day for me. There are so many technologies to learn and know how to use effectively. Our courses can't possibly include them all. We need to help students learn how to approach a new library or framework and become effective users as quickly as possible. And we need to have them using source control all the time, as ingrained habit.

One last note, if only because it made me smile. Our conversation with some of the company's developers was really interesting. At the end of the session, one of the devs handed out his business card, in case we ever wanted to ask him questions after leaving. I looked down at the card and saw...

Alan Kay's business card, redacted

... Alan Kay. Who knew that Alan was moonlighting as an application developer for a major financial services company in the Midwest? I'm not sure whether sharing a name with a titan of computer science is a blessing or a curse, but for the first time in a long while I enjoyed tucking a business card into my pocket.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

July 11, 2017 3:17 PM

Blogging as "Loud Thinking"

This morning, I tweeted a quote from Sherry Turkle's Remembering Seymour Papert that struck a chord with a few people: "Seymour Papert saw that the computer would make it easier for thinking itself to become an object of thought." Here is another passage that struck a chord with me:

At the time of the juggling lesson, Seymour was deep in his experiments into what he called 'loud thinking'. It was what he was asking my grandfather to do. What are you trying? What are you feeling? What does it remind you of? If you want to think about thinking and the real process of learning, try to catch yourself in the act of learning. Say what comes to mind. And don't censor yourself. If this sounds like free association in psychoanalysis, it is. (When I met Seymour, he was in analysis with Greta Bibring.) And if it sounds like it could you get you into personal, uncharted, maybe scary terrain, it could. But anxiety and ambivalence are part of learning as well. If not voiced, they block learning.

It occurred to me that I blog as a form of "loud thinking". I don't write many formal essays or finished pieces for my blog these days. Mostly I share thoughts as they happen and think out loud about them in writing. Usually, it's just me trying to make sense of ideas that cross my path and see where they fit in with the other things I'm learning. I find that helpful, and readers sometimes help me by sharing their own thoughts and ideas.

When I first read the phrase "loud thinking", it felt awkward, but it's already growing on me. Maybe I'll try to get my compiler students to do some loud thinking this fall.

By the way, Turkle's entire piece is touching and insightful. I really liked the way she evoked Papert's belief that we "love the objects we think with" and "think with the objects we love". (And not just because I'm an old Smalltalk programmer!) I'll let you read the rest of the piece yourself to appreciate both the notion and Turkle's storytelling.

Now, for a closing confession: I have never read Mindstorms. I've read so much about Papert and his ideas over the years, but the book has never made it to the top of my stack. I pledge to correct this egregious personal shortcoming and read it as soon as I finish the novel on my nightstand. Maybe I'll think out loud about it here soon.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

July 09, 2017 9:04 AM

What It's Like To Be A Scholar

I just finished reading Tyler Cowen's recent interview with historian Jill Lepore. When Cowen asks Lepore about E.B. White's classic Stuart Little, Lepore launches into a story that illustrates quite nicely what it's like to be a scholar.

First, she notes that she was writing a review of a history of children's literature and kept coming across throwaway lines of the sort "Stuart Little, published in 1945, was of course banned." This triggered the scholar's impulse:

And there's no footnote, no explanation, no nothing.

At the time, one of my kids was six, and he was reading Stuart Little, we were reading at night together, and I was like, "Wait, the story about the mouse who drives the little car and rides a sailboat across the pond in Central Park, that was a banned book? What do I not know about 1945 or this book? What am I missing?"

These last two sentences embody the scholar's orientation. "What don't I know about these two things I think I know well?"

And I was shocked. I really was shocked. And I was staggered that these histories of children's literature couldn't even identify the story. I got really interested in that question, and I did what I do when I get a little too curious about something, is I become obsessive about finding out everything that could possibly be found out.

Next comes obsession. Lepore then tells a short version of the story that became her investigative article for The New Yorker, which she wrote because sometimes I "just fall into a hole in the ground, and I can't get out until I have gotten to the very, very bottom of it."

Finally, three transcript pages later, Lepore says:

It was one of the most fun research benders I've ever been on.

It ends in fun.

You may be a scholar if you have this pattern. To me, one of the biggest downsides of becoming department head is having less time to fall down some unexpected hole and follow its questions until I reach the bottom. I miss that freedom.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Personal, Teaching and Learning

June 29, 2017 4:03 PM

A New Demo Compiler for My Course

a simple FizzBuzz program

Over the last couple of weeks, I have spent a few minutes most afternoons writing a little code. It's been the best part of my work day. The project was a little compiler.

One of the first things we do in my compiler course is to study a small compiler for a couple of the days. This is a nice way to introduce the stages of a compiler and to raise some of the questions that we'll be answering over the course of the semester. It also gives students a chance to see the insides of a working compiler before they write their own. I hope that this demystifies the process a little: "Hey, a compiler really is just a program. Maybe I can write one myself."

For the last decade or so, I have used a compiler called acdc for this demo, based on Chapter 2 of Crafting A Compiler by Fischer, Cytron, and LeBlanc. ac is a small arithmetic language with two types of numbers, sequences of assignment statements, and print statements. dc is a stack-based desk calculator that comes as part of many Unix installations. I whipped up a acdc compiler in Java about a decade ago and have used it ever since. Both languages have enough features to be useful as a demo but not enough to overwhelm. My hacked-up compiler is also open to improvements as we learn techniques throughout the course, giving us a chance to use them in the small before students applied them to their own project.

I've been growing dissatisfied with this demo for a while now. My Java program feels heavy, with too many small pieces to be simple enough for a quick read. It requires two full class sessions to really understand it well, and I've been hoping to shorten the intro to my course. ac is good, but it doesn't have any flow control other than sequencing, which means that it does not give us a way to look at assembly language generation with jumps and backpatching. On top of all that, I was bored with acdc; ten years is a long time to spend with one program.

This spring I stumbled on a possible replacement in The Fastest FizzBuzz in the West. It defines a simple source language for writing FizzBuzz programs declaratively. For example:

produces the output of a much larger program in other languages. Imagine being able to pull this language during your next interview for a software dev position!

This language is really simple, which means that a compiler for it can be written in relatively few lines of code. However, it also requires generating code with a loop and if-statements, which requires thinking about branching patterns in assembly language.

The "Fastest FizzBuzz" article uses a Python parser generator to create its compiler. For my course, I want something that my students can read with only their knowledge coming into the course, and I want the program to be transparent enough so that they can see directly how each stage works and how it interacts with other parts of the compiler.

I was also itching to write a program, so I did.

I wrote my compiler in Python. It performs a simple scan of the source program, taking as much advantage of the small set of simple tokens as possible. The parser works by recursive descent, which also takes advantage of the language's simple structure. The type checker makes sure the numbers all make sense and that the words are unique. Finally, to make things even simpler, the code generator produces an executable Python 3.4 program.

I'm quite hopeful about this compiler's use as a class demo. It is simple enough to read in one sitting, even by students who enter the course with weaker programming skills. Even so, the language can also be used to demonstrate the more sophisticated techniques we learn throughout the course. Consider:

  • Adding comments to the source language overwhelms the ad hoc approach I use in the scanner, motivating the use of a state machine.
  • While the parser is easily handled by recursive descent, the language is quite amenable to a simple table-driven approach, too. The table-driven parser will be simple enough that students can get the hang of the technique with few unnecessary details.
  • The type checker demonstrates walking an abstract syntax tree without worrying about too many type rules. We can focus our attention on type systems when dealing with the more interesting source language of their project.
  • The code generator has to deal with flow of control, which enables us to learn assembly language generation on a smaller scale without fully implementing code to handle function calls.
So this compiler can be a demo in the first week of the course and also serve as a running example throughout.

We'll see how well this plays in class in a couple of months. In any case, I had great fun ending my days the last two weeks by firing up emacs or IDLE and writing code. As a bonus, I used this exercise to improve my git skills, taking them beyond the small set of commands I have used on my academic projects in the past. (git rebase -i is almost my friend now.) I also wrote more pyunit tests than I have written in a long, long time, which reminded me of some of the challenges students face when trying to test their code. That should serve me well in the fall, too.

I do like writing code.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

June 12, 2017 2:15 PM

Learn from the Bees

In The Sweet Bees [paywalled], Sue Hubbell writes:

Beekeepers are an opinionated lot, each sure that his methods, and his methods alone, are the proper ones. When I first began keeping bees, the diversity of passionately held opinion bewildered me, but now that I have hives in locations scattered over a thousand-square-mile area I think I understand it.... Frosts come earlier in some places than in others. Spring comes later. Rainfall is not the same. The soils, and the flowering plants they support, are unlike. Through the years, I have learned that as a result of all these variations I must keep the bees variously. Most people who keep bees have only a few hives, and have them all in one place. They find it difficult to understand why practices that have proved successful for them do not work for others. But I have learned that I must treat the bees in one yard quite differently from the way I do those even thirty miles away. The thing to do, I have discovered, is to learn from the bees themselves.

Even though I've taught at only two universities, I've learned this lesson over the years in many ways that don't require physical distance. Teaching novices in an intro course is different from teaching seniors. Teaching a programming course is different from teaching discrete structures or theory of computation. Teaching AI is different from teaching operating systems. I have learned that I must teach differently in different kinds of courses.

In an instructional setting, even more important are the bees themselves. I've been teaching Programming Languages every spring for the last years, and each group of students has been a little different. The course goes better when I have -- and take -- the time to make adjustments according to what I learn over the course of the semester about the particular set of students I have. This spring, I did not recognize the need to adapt quickly enough, and I feel like I let some of the students down.

You sometimes hear faculty talk about students "back in the old days". One thing is certain: the students we had then probably were different from the students we have now. But they were also different from the students that came before them. Each group is new, made up of individuals with their own backgrounds and their own goals.

It's nice when students are similar enough to what we expect that we can take advantage of what worked well last time. We just can't count on that happening all that often. Our job is to teach the students in class right now.

(I first encountered Hubbell's article in To Teach, by William Ayers. I gave a short review of it in yesterday's post.)

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 11, 2017 9:40 AM

Two True Sentences about Teaching Math

Math phobia is a common affliction of [K-12] teachers, and something that must be resisted if strong and able students are our goal.

Our own confusion about math can be an important aid in our teaching, if we take it seriously.

That second sentence applies to more than math, and more than K-12.

These come from To Teach, by William Ayers. This book is about teaching in K-12 schools, especially younger grades, with no particular focus on math or any other subject. These sentences come from a chapter on "liberating the curriculum", in which Ayers talks about specific issues in teaching reading, math, science, and social studies. Otherwise, the book is about ways of thinking about learning that respect the individual and break down artificial boundaries between areas of knowledge.

Teaching at a university is different, of course, because we are working with older, more mature students. They are more capable of directing their own learning and are, at least in my discipline, usually taking courses as part of a major they themselves have chosen. You would think that engagement and motivation would take on much different forms in the college setting.

However, I think that most of what Ayers says applies quite well to teaching college. This is especially true when students come to us hamstrung by a K-12 education such that they cannot, or at least do not as a matter of habit, take control of their learning. But I think his advice is true of good teaching anywhere, at least in spirit:

  • Get to know each student.
  • Create an environment that encourages and supports learning.
  • Build bridges to ideas across the discipline and to ideas in other disciplines.
  • Engage constantly with the question of what experiences will most help students on the path to wherever they are going.

One of my favorite lines from the book is You can learn everything from anything. Start with any topic in the CS curriculum, or any project that someone wants to build, and you will eventually touch every part of the field. I think we could do some interesting things with the CS curriculum by focusing courses on projects instead of topic areas. I love how Ayers suggests bringing this mindset even to kindergarten students.

Ayers's book is a thin volume, the sort I like, with good stories and thought-provoking claims about how we approach students and schools. Eugene sez: two thumbs up.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 08, 2017 12:10 PM

We Need a Course on Mundane Data Types

Earlier this month, James Iry tweeted:

Every CS degree covers fancy data structures. But what trips up more programmers? Times. Dates. Floats. Non-English text. Currencies.

I would like to add names to Iry's list. As a person who goes by his middle name and whose full legal name includes a suffix, I've seen my name mangled over the years in ways you might not imagine -- even by a couple of computing-related organizations that shall remain nameless. (Ha!) And my name presents only a scant few of the challenges available when we consider all the different naming conventions around the world.

This topic would make a great course for undergrads. We could call it "Humble Data Types" or "Mundane Data Types". My friends who program for a living know that these are practical data types, the ones that show up in almost all software and which consume an inordinate amount of time. That's why we see pages on the web about "falsehoods programmers believe" about time, names, and addresses -- another one for our list!

It might be hard to sell this course to faculty. They are notoriously reluctant to add new courses to the curriculum. (What would it displace?) Such conservatism is well-founded in a discipline that moves quickly through ideas, but this is a topic that has been vexing programmers for decades.

It would also be hard to sell the course to students, because it looks a little, well, mundane. I do recall a May term class a few years ago in which a couple of programmers spent days fighting with dates and times in Ruby while building a small accounting system. That certainly created an itch, but I'm not sure most students have enough experience with such practical problems before they graduate.

Maybe we could offer the course as continuing education for programmers out in the field. They are the ones who would appreciate it the most.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

May 31, 2017 2:28 PM

Porting Programs, Refactoring, and Language Translation

In his commonplace book A Certain World, W.H. Auden quotes C.S. Lewis on the controversial nature of tramslation:

[T]ranslation, by its very nature, is a continuous implicit commentary. It can become less tendentious only by becoming less of a translation.

Lewis was merely acknowledging a truth about language: Translators must have a point of view, and often that point of view will be controversial.

I once saw Kurt Vonnegut speak with a foreign language class here many years ago. One of the students asked him what he thought about the quality of the translations done for his book. Vonnegut laughed and said that his books were so peculiar and so steeped in Americana that translating one was akin to writing a new book. He said that his translators deserved all the royalties from the books they created by translating him. They had to write brand new works.

These memories came to mind again recently while I was reading Tyler Cowen's conversation with Jhumpa Lahiri, especially when Lahiri said this:

At one point I was talking about this idea, in antiquity: in Latin, the word for "translator" is "interpreter". I teach translation now, and I talk a lot to my students about translation being the most intimate form of reading and how there was the time when translating and interpreting and analyzing were all one thing.

As my mind usually does, it began to think about computer programs.

Like many programmers, I often find myself porting a program from one language to another. This is clearly translation but, as Vonnegut and and Lahiri tell us, it is also a form of interpretation. To port a piece of code, I have to understand its meaning and express that meaning in a new language. That language has its own constructs, idioms, patterns, and set of community practices and expectations. To port a program, one must have a point of view, so the process can be, to use Lewis's word, tendentious.

I often refactor code, too, both my own programs and programs written by others. This, too, is a form of translation, even though it leaves the new code written in the same language as the original. Refactoring is necessarily an opinionated act, and thus tendentious.

Occasionally, I refactor a program in order to learn what it does and how it does it. In those cases, I'm not judging the original code as anything but ill-suited to my current state of knowledge. Even so, when I get done, I usually like my version better, if only a little bit. It expresses what I learned in the process of rewriting the code.

It has always been hard for me to port a program without refactoring it, and now I understand why. Both activities are a kind of translation, and translation is by its nature an activity that requires a point of view.

This fall, I will again teach our "Translation of Programming Languages" course. Writing a compiler requires one to become intimate not only with specific programs, the behavior of which the compiler must preserve, but also the language itself. At the end of the project, my students know the grammar, syntax, and semantics of our source language in a close, almost personal way. The target language, too. I don't mind if my students develop a strong point of view, even a controversial one, along the way. (I'm actually disappointed if the stronger students do not!) That's a part of writing new software, too.

Posted by Eugene Wallingford | Permalink | Categories: General, Patterns, Software Development, Teaching and Learning

May 30, 2017 4:28 PM

Learning by Guided Struggle

A few years ago, someone asked MathOverflow, "Why do so many textbooks have so much technical detail and so little enlightenment?" Some CS textbooks suffer from this problem, too, though these days the more likely case is that the book tries to provide too much context. They try to motivate so much that they drown the reader in a lot of unhelpful words.

The top answer on MathOverflow (via Brian Marick) points out that the real problem does not usually lie in the lack of motivation or context provided by textbooks. The real goal is to learn how to do math, not "know" it. That is even more true of software developent. A textbook can't really teach to write programs; most of that is learned through doing itself. Perhaps the best purpose that the text can serve, says the answer, is to show the reader what he or she needs to learn. From there, the reader must go off and practice.

How does learning occur from there?

Based on my own experience as both a student and a teacher, I have come to the conclusion that the best way to learn is through "guided struggle". You have to do the work yourself, but you need someone else there to either help you over obstacles you can't get around despite a lot of effort or provide you with some critical knowledge (usually the right perspective but sometimes a clever trick) you are missing. Without the prior effort by the student, the knowledge supplied by a teacher has much less impact.

Some college CS students seem to understand this, or perhaps they simply get lucky because they are motivated to program for some other reason. They go off and try to do something using the knowledge they have. Then they come to class, or to the prof's office hours, to ask questions about what does not go smoothly. Students who skip the practice and hope that lectures will soak into them like a magic balm generally find that they don't know much when they attempt problems after class.

The MathOverflow answer matches up pretty well with my experience. Teachers and written material can have strong positive effect on learning, but they are most effective once the student has engaged with the material by trying to solve problems or write code. The teacher's job then has two parts: First, create conditions in which students can work productively. Second, pay close attention to what students are doing, diagnose misconceptions and mistakes, and help students get back onto a productive path by pointing out missing practices or bits of knowledge.

All of this reminds me of some of mymore effective class sessions teaching novice programmers, using design patterns. A typical session looks something like this:

  • I give the students a problem to solve.
  • Students work on a solution, using techniques that have worked in the past.
  • They encounter problems, because the context around the problem has shifted in ways that they can't see given only what they know.
  • We discuss the forces at play and tease out the underlying problem.
  • I demonstrate the pattern's solution.
  • Ahhhh.

This is a guided struggle in the small. Students then go off to write a larger program that lets them struggle a bit more, and we discuss whatever gets in their way.

A final note... One of the comments on the answer points out that a good lecture can "do" math (or CS), rather than "tell", and that such lectures can be quite effective. I agree, but in my experience this is one of the hardest skills for a professor to develop. Once I have solved a problem, it is quite difficult for me to make it look to my students as if I am solving it anew in class. The more ingrained the skill, the harder it is for me to lecture about it in a way that is more helpful than telling a story. Such stories are an essential tool in the teacher's toolbox, but their lies more in motivating students than in teaching them how to write programs. Students still have to go off and do the hard work themselves. The teacher's job is to guide them through their struggles.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

May 04, 2017 4:07 PM


In an essay in The Guardian, writer George Saunders reflects on having written his first novel after many years writing shorter fiction. To a first approximation, he found the two experiences to be quite similar. In particular,

What does an artist do, mostly? She tweaks that which she's already done.

I read this on a day when I had just graded thirty-plus programming assignments from my junior/senior-level Programming Languages courses, and this made me think of student programmers. My first thought was snarky, and only partly tongue-in-cheek: Students write and then submit. Who has the time or interest to tweak?

My conscience quickly got the better of me, and I admitted that this was unfair. In a weak moment at the end of a long day, it's easy to be dismissive and not think about students as people who face all sorts of pressures both in and out of the classroom. Never forget Hanlon's Razor, my favorite formulation of which is:

Never attribute to malice or stupidity that which can be explained by moderately rational individuals following incentives in a complex system of interactions.

Even allowing the snark, my first thought was inaccurate. The code students submit is often the end result of laborious tweaking. The thing is, most students tweak only while the code gives incorrect answers. In the worst case, some students tweak and tweak, employing an age-old but highly inefficient software development methodology: Make another change and see if it works.

This realization brought to mind Kent Beck's Rules of Simple Design:

  1. passes the tests
  2. reveals intention
  3. has no duplication
  4. has the fewest elements possible

Most students are under time pressures that make artistry a luxury good; they are happy to find time to make their code work at all. If the code passes the tests, it's probably good enough for now.

But there is more to the student's willingness to stop tinkering so soon than just external pressures. It takes a lot of programming experience and a fair amount of time to come to even appreciate Rules 2 through 4. Why does it matter if code reveals the programmer's intention, in terms of either art or engineering? What's the big deal about a little duplication? The fewest elements? -- making that happen takes time that could be spent on something much more interesting.

I am coming to think of Kent's rules as a sort of Bloom's taxonomy for the development of programming expertise. Students start at Level 1, happy to write code that achieves its stated purpose. As they grow, programmers move through the rules, mastering deeper levels of understanding of design, simplicity, and, yes, artistry. They don't move through the stages in a purely linear fashion, but they do tend to master the rules in roughly the order listed above.

Today is a day of empathy for my novice programmers. As I write this, they are writing the final exam in my course. I hope that in a few weeks, after the blur of a busy semester settles in their minds, they reflect a bit and see that they have made progress as programmers -- and that they can now ask better questions about the programming languages they use than they could at the beginning of the course.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

April 07, 2017 1:33 PM

Two Very Different Kinds of Student

The last sentence of each of these passages reminds me of some of the students over the years.

First this, from Paul Callaghan's The Word Chain Kata:

One common way to split problems is via the "generate and test" pattern, where one component suggests results and the other one discards invalid ones. (In my experience, undergrad programmers are experts in this pattern, although they tend to use it as a [software development] methodology--but that's another story.)

When some students learn to program for the first time, they start out by producing code that looks like something they have seen before, trying it out, and then tinkering with it until it works or until they become exasperated. (I always hope that they act on their exasperation by asking me for help, rather than by giving up.) These students usually understand little bits of the code locally, but they don't really understand the program or function as a whole. Yet, somehow, they find a way to make it work.

It's surprising how far some students can get in a course of study by programming this way. (That's why Callaghan calling the approach a methodology made me smile.) It's unfortunate, too, because eventually the approach hits a wall when problems and domains become more challenging. Or when they run into a course where they program in Racket, in which one misplaced parenthesis can cause an otherwise perfect piece of code to implode. Lisp-like languages do not provide a supportive environment for this kind of "programming by wandering around".

And then there's this, from Andy Hertzfeld's fun little story about the writing of the classic manual Inside Macintosh:

Pretty soon, I figured out that if Caroline had trouble understanding something, it probably meant that the design was flawed. On a number of occasions, I told her to come back tomorrow after she asked a penetrating question, and revised the API to fix the flaw that she had pointed out. I began to imagine her questions when I was coding something new, which made me work harder to get things clearer before I went over them with her.

In this story, Caroline is not a student, but a young new writer assigned to the Mac documentation team. Still, she reminds me of students who are as delightful to work with as generate-and-test programmers can be frustrating. These students pay attention. They ask good questions, ones that often challenge the unstated assumptions underlying what we have explained before. At first, this can seem frustrating to us teachers, because we have to formulate answers for things that should be obvious. But that's the point: they aren't obvious, at least not to everyone, and us thinking they are obvious is inhibiting our teaching.

Last semester, I had one team of students in my compilers class that embodied this attitude. They asked questions no one had ever bothered to ask me before. At first, I thought, "How can these guys not understand such basic material?" Like Hertzfeld, though, pretty soon I figured out that their questions were exposing holes or weaknesses in my lectures, examples, and sample code. I began to anticipate their questions as I prepared for class. Their questions helped me see ways to make my course better.

As along so many other dimensions, part of the challenge in teaching CS is the wide variation in the way students study, learn, and approach their courses. It is also a part of the great fun of teaching, especially when you encounter the Carolines and Averys who push me to get better.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

April 02, 2017 12:02 PM

Reading an Interview with John McPhee Again, for the First Time

"This weekend I enjoyed Peter Hessler's interview of McPhee in The Paris Review, John McPhee, The Art of Nonfiction No. 3."

That's a direct quote from this blog. Don't remember it? I don't blame you; neither do I. I do remember blogging about McPhee back when, but as I read the same Paris Review piece again last Sunday and this, I had no recollection of reading it before, no sense of déjà vu at all.

Sometimes having a memory like mine is a blessing: I occasionally get to read something for the first time again. If you read my blog, then you get to read my first impressions for a second time.

I like this story that McPhee told about Bob Bingham, his editor at The New Yorker:

Bingham had been a writer-reporter at The Reporter magazine. So he comes to work at The New Yorker, to be a fact editor. Within the first two years there, he goes out to lunch with his old high-school friend Gore Vidal. And Gore says, What are you doing as an editor, Bobby? What happened to Bob Bingham the writer? And Bingham says, Well, I decided that I would rather be a first-rate editor than a second-rate writer. And Gore Vidal draws himself up and says, And what is wrong with a second-rate writer?

I can just hear the faux indignation in Vidal's voice.

McPhee talked a bit about his struggle over several years to write a series of books on geology, which had grown out of an idea for a one-shot "Talk of the Town" entry. The interviewer asked him if he ever thought about abandoning the topic and moving on to something he might enjoy more. McPhee said:

The funny thing is that you get to a certain point and you can't quit. Because I always worried: if you quit, you'll quit again. The only way out was to go forward, to learn your way and write your way out of it.

I know that feeling. Sometimes, I really do need to quit something and move on, but I always wonder whether quitting this time will make it easier to do next time. Because sometimes, I need to stick it out and, as McPhee says, learn my way out of the difficulty. I have no easy answers for knowing when quitting is the right thing to do.

Toward the end of the interview, the conversation turned to the course McPhee teaches at Princeton, once called "the literature of fact". The university first asked him to teach on short notice, over the Christmas break in 1974, and he accepted immediately. Not everyone thought it was a good idea:

One of my dear friends, an English teacher at Deerfield, told me: Do not do this. He said, Teachers are a dime a dozen -- writers aren't. But my guess is that I've been more productive as a writer since I started teaching than I would have been if I hadn't taught. In the overall crop rotation, it's a complementary job: I'm looking at other people's writing, and the pressure's not on me to do it myself. But then I go back quite fresh.

I know a lot of academics who feel this way. Then again, it's a lot easier to stay fresh in one's creative work if one has McPhee's teaching schedule, rather than a full load of courses:

My schedule is that I teach six months out of thirty-six, and good Lord, that leaves a lot of time for writing, right?

Indeed it does. Indeed it does.

On this reading of the interview, I marked only two passages that I wrote about last time. One came soon after the above response, on how interacting with students is its own reward. The other was a great line about the difference between mastering technique and having something to say: You demonstrated you know how to saddle a horse. Now go find the horse.

That said, I unconsciously channeled this line from McPhee just yesterday:

Writing teaches writing.

We had a recruitment event on campus, and I was meeting with a dozen or so prospective students and their entourages. We were talking about our curriculum, and I said a few words about our senior project courses. Students generally like these courses, even though they find them difficult. The students have never had to write a big program over the course of several months, and it's harder than it looks. The people who hire our graduates like these courses, too, because they know that these courses are places where students really begin to learn to program.

In the course of my remarks, I said something to the effect, "You can learn a lot about programming in classes where you study languages and techniques and theory, but ultimately you learn to write software by writing software. That's what the project courses are all about." There were a couple of experienced programmers in the audience, and they were all nodding their heads. They know McPhee is right.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

March 29, 2017 4:16 PM

Working Through A Problem Manually

This week, I have been enjoying Eli Bendersky's two-article series "Adventures in JIT Compilation":

Next I'll follow his suggestion and read the shorter How to JIT - An Introduction.

Bendersky is a good teacher, at least in the written form, and I am picking up a lot of ideas for my courses in programming languages and compilers. I recommend his articles and his code highly.

In Part 2, Bendersky says something that made me think of my students:

One of my guiding principles through the field of programming is that before diving into the possible solutions for a problem (for example, some library for doing X) it's worth working through the problem manually first (doing X by hand, without libraries). Grinding your teeth over issues for a while is the best way to appreciate what the shrinkwrapped solution/library does for you.

The presence or absence of this attitude is one of the crucial separators among CS students. Some students come into the program with this mindset already in place, and they are often the ones who advance most quickly in the early courses. Other students don't have this mindset, either by interest or by temperament. They prefer to solve problems quickly using canned libraries and simple patterns. These students are often quite productive, but they sometimes soon hit a wall in their learning. When a student rides along the surface of what they are told in class, never digging deeper, they tend to have a shallow knowledge of how things work in their own programs. Again, this can lead to a high level of productivity, but it also produces brittle knowledge. When something changes, or the material gets more difficult, they begin to struggle. A few of the students eventually develop new habits and move nicely into the group of students who likes to grind. The ones who don't make the transition continue to struggle and begin to enjoy their courses less.

There is a rather wide variation among undergrad CS students, both in their goals and in their preferred styles or working and learning. This variation is one of the challenges facing profs who hope to reaching the full spectrum of students in their classes. And helping students to develop new attitudes toward learning and doing is always a challenge.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 10, 2017 2:51 PM

Reading Is A Profoundly Creative Act

This comes from Laura Miller, a book reviewers and essayist for Slate, in a Poets & Writers interview:

I also believe that reading is a profoundly creative act, that every act of reading is a collaboration between author and reader. I don't understand why more people aren't interested in this alchemy. It's such an act of grace to give someone else ten or fifteen hours out of your own irreplaceable life, and allow their voice, thoughts, and imaginings into your head.

I think this is true of all reading, whether fiction or nonfiction, literary or technical. I often hear CS profs tell their students to read "actively" by trying code out in an interpreter, asking continually what the author means, and otherwise engaging with the material. Students who do have a chance to experience what Miller describes: turning over a few hours of their irreplaceable lives to someone who understands a topic well, allow their voice, thoughts, and imaginings into their heads, and coming out on the other end of the experience with new thoughts -- and maybe even a new mind.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

March 05, 2017 10:53 AM

"Flying by Instruments" and Learning a New Programming Style

Yesterday afternoon I listened to a story told by someone who had recently been a passenger in a small plane flown by a colleague. As they climbed to their cruising altitude, which was clear and beautiful, the plane passed through a couple thousand feet of heavy clouds. The pilot flew confidently, having both training and experience in instrument flight.

The passenger telling the story, however, was disoriented and a little scared by being in the clouds and not knowing where they were heading. The pilot kept him calm by explaining the process of "flying by instruments" and how he had learned it. Sometimes, learning something new can give us confidence. Other times, just listening to a story can distract us enough to get us through a period of fear.

This story reminded me of a session early in my programming languages course, when students are learning Racket and functional programming style. Racket is quite different from any other language they have learned. "Don't dip your toes in the water," I tell them. "Get wet."

For students who prefer their learning analogies not to involve potential drowning -- that is, after all, the sensation many of them report feeling as they learn to cope with all of Racket's parentheses for the first time -- I relate an Alan Kay story that talks about learning to fly an airplanes after already knowing how to drive a car. Imagine what the world be like if everyone refused to learn how to fly a plane because driving was so much more comfortable and didn't force them to bend their minds a bit? Sure, cars are great and serve us well, but planes completely change the world by bringing us all closer together.

I have lost track of where I had heard or read Kay telling that story, so when I wrote up the class notes, I went looking for a URL to cite. I never found one, but while searching I ran across a different use of airplanes in an analogy that I have since worked into my class. Here's the paragraph I use in my class notes, the paragraph I thought of while listening to the flying-by-instruments story yesterday:

The truth is that bicycles and motorcycles operate quite differently than wheeled vehicles that keep three or more wheels on the ground. For one thing, you steer by leaning, not with the handlebars or steering wheel. Learning to fly an airplane gives even stronger examples of having to learn that your instincts are wrong, and that you have to train yourself to "instinctively" know not only that you turn by banking rather than with the rudder, but that you control altitude primarily with the throttle, not the elevators, speed primarily with the elevators not the throttle, and so forth.

Learning to program in a new style, whether object-oriented, functional, or concatenative, usually requires us to overcome deeply-ingrained design instincts and to develop new instincts that feel uncomfortable while we are learning. Developing new instincts takes some getting used to, but it's worth the effort, even if we choose not to program much in the new style after we learn it.

Now I find myself thinking about what it means to "fly by instruments" when we program. Is our unit testing framework one of the instruments we come to rely on? What about a code smell detector such as Reek? If you have thoughts on this idea, or pointers to what others have already written, I would love to hear from you.

Postscript.   I originally found the passage quoted above in a long-ish article about Ruby and Smalltalk, but that link has been dead for a while. I see that the article was reposted in a Ruby Buzz Forum message called On Ceremony and Training Wheels.

Oh, and if you know where I can find the Alan Kay story I went looking for online, I will greatly appreciate any pointers you can offer!

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

February 28, 2017 3:47 PM

Comments on Comments

Over the last couple of days, a thread on the SIGCSE mailing list has been revisiting the well-tilled ground of comments in code. As I told my students at the beginning of class this semester, some of my colleagues consider me a heretic for not preaching the Gospel of Comments in Code. Every context seems to have its own need for, and expectations of, comments. Wherever students end up working, both while in school and after graduation, their employers will set a standard and expect them to follow. They will figure it out.

In most of my courses, I define a few minimal standard, try to set a good example in the code I give my students, and otherwise don't worry much about comments. Part of my example is that different files I give them are commented differently, depending on the context. A demo of an idea, a library to be reused in the course, and an application are different enough that they call for different kinds of comments. In a course such as compiler development, I require more documentation, both in and out of the code. Students live with that code for a semester and come to value some of their own comments many weeks later.

Anyway, the SIGCSE thread included two ideas that I liked, though they came from competing sides of the argument. One asserted that comments are harmful, because:

They're something the human reader can see but the computer can't, and therefore are a source of misunderstanding.

I love the idea of thinking in terms of misunderstandings between humans and the computer.

The other responded to another poster's suggestion that students be encouraged to write comments with themselves in mind: What would you like to know if you open this code six months from now? The respondent pointed out that this is unreasonable: Answering that question requires...

... a skill that is at least on par with good programming skills. Certainly new CS students are unable to make this kind of decision.

The thread has been a lot of fun to read. I remain mostly of the view that:

  • It's better to write code that says what it means and thus needs as few comments as possible. This is a skill students can and should work on all the time time.

  • If the code is likely to conflict with the expectations of the people most likely to read your code, then add a comment. This part depends a lot on context and experience. Students are just now earning their experience, and the context in which they work changes from course to course and job to job.
Students who care about programming, or who come to care about it over time, will care (or come to care) about comments, too.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

February 23, 2017 4:08 PM

Surrounding Yourself with Beginners

This comment at the close of a recent Dan Meyer post struck close to home:

I haven't found a way to generate these kinds of insights about math without surrounding myself with people learning math for the first time.

I've learned a lot about programming from teaching college students. Insights can come at all levels, from working with seniors who are writing compilers as their first big project, through midstream students who are learning OOP or functional programming as a second or third style, right down to beginners who are seeing variables and loops and functions for the first time.

Sometimes an insight comes when a student asks a new question, or an old question at the right time. I had a couple of students in my compiler course last fall who occasionally asked the most basic questions, especially about code generation. Listening to their questions and creating new examples to illustrate my answers helped me think differently about the run-time system.

Other times, they come while listening to students talk among themselves. One student's answer to another student's question can trigger an entirely new way for me to think about a concept I think I understand pretty well. I don't have any recent personal examples in mind, but this sort of experience seems to be part of what triggered Meyer's post.

People are always telling us to "be the least experienced person in the room", to surround ourselves with "smarter" or more experienced people and learn from them. But there is a lot to be learned from programmers who are just starting out. College profs have that opportunity all the time, if they are willing to listen and learn.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

February 10, 2017 3:55 PM

Follow-Up on Learning by Doing and Ubiquitous Information

A few quick notes on my previous post about the effect of ubiquitous information on knowing and doing.


The post reminded a reader of something that Guy Steele said at DanFest, a 2004 festschrift in honor of Daniel Friedman's 60th birthday. As part of his keynote address, Steele read from an email message he wrote in 1978:

Sussman did me a very big favor yesterday -- he let me flounder around trying to build a certain LISP interpreter, and when I had made and fixed a critical bug he then told me that he had made (and fixed) the same mistake in Conniver. I learned a lot from that bug.

Isn't that marvelous? "I learned a lot from that bug."

Thanks to this reader for pointing me to a video of Steele's DanFest talk. You can watch this specific passage at the 12:08 mark, but really: You now have a link to an hour-long talk by Guy Steele that is titled "Dan Friedman--Cool Ideas". Watch the entire thing!


If all you care about is doing -- getting something done -- then ubiquitous information is an amazing asset. I use Google and StackOverflow answers quite a bit myself, mostly to navigate the edges of languages that I don't use all the time. Without these resources, I would be less productive.


Long-time readers may have read the story about how I almost named this blog something else. ("The Euphio Question" still sets my heart aflutter.) Ultimately I chose a title that emphasized the two sides of what I do as both a programmer and a teacher. The intersection of knowing and doing is where learning takes place. Separating knowing from doing creates problems.

In a post late last year, I riffed on some ideas I had as I read Learn by Painting, a New Yorker article about an experiment in university education in which everyone made art as a part of their studies.

That article included a line that expressed an interesting take on my blog's title: "Knowing and doing are two sides of the same activity, which is adapting to our environment."

That's cool thought, but a rather pedestrian sentence. The article includes another, more poetic line that fits in nicely with the theme of the last couple of days:

Knowing is better than not knowing, but knowing without doing is as good as not knowing.

If I ever adopt a new tagline for my blog, it may well be this sentence. It is not strictly true, at least in a universal sense, but it's solid advice nonetheless.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

February 09, 2017 4:25 PM

Knowing, Doing, and Ubiquitous Information

I was recently reading an old bit-player entry on computing number factoids when I ran across a paragraph that expresses an all-too-common phenomenon of the modern world:

If I had persisted in my wrestling match, would I have ultimately prevailed? I'll never know, because in this era of Google and MathOverflow and StackExchange, a spoiler lurks around every cybercorner. Before I could make any further progress, I stumbled upon pointers to the work of Ira Gessel of Brandeis, who neatly settled the matter ... more than 40 years ago, when he was an undergraduate at Harvard.

The matter in this case was recognizing whether an arbitrary n is a Fibonacci number or not, but it could be have been just about anything. If you need an answer to almost any question these days, it's already out there, right a your fingertips.

Google and StackExchange and MathOverflow are a boon for knowing, but not so much for doing. Unfortunately, doing often leads to a better kind of knowing. Jumping directly to the solution can rob us of some important learning. As Hayes reminds us in his articles, it also can also deprive us of a lot of fun.

You can still learn by doing and have a lot of fun doing it today -- if you can resist the temptation to search. After you struggle for a while and need some help, then having answers at our fingertips becomes a truly magnificent resource and can help us get over humps we could never have gotten over so quickly in even the not-the-so-distant past.

The new world puts a premium on curiosity, the desire to find answers for ourselves. It also values self-denial, the ability to delay gratification while working hard to find answer that we might be able to look up. I fear that this creates a new gap for us to worry about in our education systems. Students who are curious and capable of self-denial are a new kind of "haves". They have always had a leg up in schools, but ubiquitous information magnifies the gap.

Being curious, asking questions, and wanting to create (not just look up) answers have never been more important to learning.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 28, 2017 8:10 AM

Curiosity on the Chessboard

I found a great story from Lubomir Kavalek in his recent column, Chess Champions and Their Queens. Many years ago, Kavalek was talking with Berry Withuis, a Dutch journalist, about Rashid Nezhmedtinov, who had played two brilliant queen sacrifices in the span of five years. The conversation reminded Withuis of a question he once asked of grandmaster David Bronstein:

"Is the Queen stronger than two light pieces?"

(The bishop and knight are minor, or "light", pieces.)

The former challenger for the world title took the question seriously. "I don't know," he said. "But I will tell you later."

That evening Bronstein played a simultaneous exhibition in Amsterdam and whenever he could, he sacrificed his Queen for two minor pieces. "Now I know," he told Withuis afterwards. "The Queen is stronger."

How is that for an empirical mind? Most chessplayers would have immediately answered "yes" to Withuis's question. But Bronstein -- one of the greatest players never to be world champion and author of perhaps the best book of tournament analysis in history -- didn't know for sure. So he ran an experiment!

We should all be so curious. And humble.

I wondered for a while if Bronstein could have improved his experiment by channeling Kent Beck's Three Bears pattern. (I'm a big fan of this learning technique and mention it occasionally here, most recently last summer.) This would require him to play many games from the other side of the sacrifice as well, with a queen against his opponents' two minor pieces. Then I realized that he would have a hard time convincing any of his opponents to sacrifice their queens so readily! This may be the sort of experiment that you can only conduct from one side, though in the era of chess computers we could perhaps find, or configure, willing collaborators.

Posted by Eugene Wallingford | Permalink | Categories: General, Patterns, Teaching and Learning

January 22, 2017 9:26 AM

To Teach is to Counsel Possibility and Patience

As I settle into a new semester of teaching students functional programming and programming languages, I find myself again in the role of grader of, and commenter, on code. This passage from Tobias Wolff in Paris Review interview serves as a guide for me:

Now, did [Pound] teach Eliot to write? No. But he did help him see that there were more notes to be played he was playing. That is the kind of thing I hope to do. And to counsel patience -- the beauty of patience, which is not a virtue of the young.

Students often think that learning to program is all about the correctness of their code. Correctness matters, but there's a lot more. Knowing what is possible and learning to be patient as they learn often matter more than mere correctness. For some students, it seems, those lessons must begin before more technical habits can take hold.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

January 20, 2017 11:38 AM

Build the Bridge

On the racket-users mailing list yesterday, Matthias Felleisen issued "a research challenge that is common in the Racket world":

If you are here and you see the blueprints for paradise over there, don't just build paradise. Also build the bridge from here to there.

This is one of the things I love about Racket. And I don't use even 1% of the goodness that is Racket and its ecosystem.

Over the last couple of years, I have been migrating my Programming Languages course from a Scheme subset of Racket to Racket itself. Sometimes, this is simply a matter of talking about Racket, not Scheme. Others, it means using some of the data structures, functions, and tools Racket provides rather than doing without or building our own. Occasionally, this shift requires changing something I do in class, because Racket is fussier than Scheme in some regards. That's usually a good thing, because the change makes Racket a better language for engineering big programs. In general, though, the shift goes smoothly.

Occasionally, the only challenge is a personal one. For example, I decided to use first and rest this semester when working with lists, instead of car and cdr. This should make some students' lives better. Learning a new language and a new style and new IDE all at once can be tough for students with only a couple of semesters' programming experience, and using words that mean what they say eliminates one unnecessary barrier. But, as I tweeted, I don't feel whole or entirely clean when I do so. As my college humanities prof taught me through Greek tragedies, old habits die hard, if at all.

One of my goals for the course this semester is to have the course serve as a better introduction to Racket for students who might be inclined to take advantage of its utility and power in later courses, or who simply want to enjoy working in a beautiful language. I always seem to have a few who do, but it might be nice if even more left the course thinking of Racket as a real alternative for their project work. We'll see how it goes.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

January 11, 2017 2:22 PM

An Undergraduate Research Project for Spring

Coming into the semester, I didn't have any students doing their undergraduate research under my supervision. That frees up some time each week, which is nice, but leaves my semester a bit poorer. Working with students one-on-one is one of the best parts of this job, even more so in relief against administrative duties. Working on these projects makes my weeks better, even when I don't have as much time to devote to them as I'd like.

Yesterday, a student walked in with a project that makes my semester a little busier -- and much more interesting. Last summer, he implemented some ideas on extensible effects in Haskell and has some ideas for ways to make the system more efficient.

This student knows a lot more about extensible effects and Haskell than I do, so I have some work to do just to get ready to help. I'll start with Extensible Effects: An Alternative to Monad Transformers, the paper by Oleg Kiselyov and his colleagues that introduced the idea to the wider computing community. This paper builds on work by Cartwright and Felleisen, published over twenty years ago, which I'll probably look at, too. The student has a couple of other things for me to read, which will appear in his more formal proposal this week. I expect that these papers will make my brain hurt, in the good way, and am looking forward to diving in.

In the big picture, most undergrad projects in my department are pretty minor as research goes. They are typically more D than R, with students developing something that goes beyond what they learn in any course and doing a little empirical analysis. The extensible effects project is much more ambitious. It builds on serious academic research. It works on a significant problem and proposes something new. That makes the project much more exciting for me as the supervisor.

I hope to report more later, as the semester goes on.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 08, 2017 9:48 AM

Finding a Balance Between Teaching and Doing

In the Paris Review's The Art of Fiction No. 183, the interviewer asks Tobias Wolff how he balances writing with university teaching. Wolff figures that teaching is a pretty good deal:

When I think about the kinds of jobs I've had and the ways I've lived, and still managed to get work done--my God, teaching in a university looks like easy street. I like talking about books, and I like encountering other smart, passionate readers, and feeling the friction of their thoughts against mine. Teaching forces me to articulate what otherwise would remain inchoate in my thoughts about what I read. I find that valuable, to bring things to a boil.

That reflects how I feel, too, as someone who loves to do computer science and write programs. As a teacher, I get to talk about cool ideas every day with my students, to share what I learn as I write software, and to learn from them as they ask the questions I've stopped asking myself. And they pay me. It's a great deal, perhaps the optimal point in the sort of balance that Derek Sivers recommends.

Wolff immediately followed those sentences with a caution that also strikes close to home:

But if I teach too much it begins to weigh on me--I lose my work. I can't afford to do that anymore, so I keep a fairly light teaching schedule.

One has to balance creative work with the other parts of life that feed the work. Professors at research universities, such as Wolff at Stanford, have different points of equilibrium available to them than profs at teaching universities, where course loads are heavier and usually harder to reduce.

I only teach one course a semester, which really does help me to focus creative energies around a smaller set of ideas than a heavier load does. Of course, I also have the administrative duties of a department head. They suffocate time and energy in a much less productive way than teaching does. (That's the subject of another post.)

Why can't Wolff afford to teach too many courses anymore? I suspect the answer is time. When you reach a certain age, you realize that time is no longer an ally. There are only so many years left, and Wolff probably feels the need to write more urgently. This sensation has been seeping into my mind lately, too, though I fear perhaps a bit too slowly.


(I previously quoted Wolff from the same interview in a recent entry about writers who give advice that reminds us that there is no right way to write all programs. A lot of readers seemed to like that one.)

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

December 30, 2016 12:42 PM

Looking Closer at My Course is Hard -- and Helpful

The CS faculty has decided to create common syllabi for all courses in the department. The motivation to do this came from several directions, including a need to meet university requirements regarding "outcomes assessment" and a desire to make sections taught by different instructors more consistent within and across semesters. But it will also help instructors improve their courses. Faculty teaching upper-division courses will have a more better sense of what students coming into their courses should already know, and faculty teaching lower-division courses will have a better sense of what students their students need to be able to do in their upcoming courses.

Our first pass at this is for each faculty member to use a common format to describe one of his or her courses. The common format requires us to define in some detail the purpose, goals, outcomes, and content of the course. Of course, we all have syllabi for our courses that cover some or all of these things, but now we are expected to make all the elements concrete enough that the syllabus can be used by other faculty to teach the course.

For my first attempt, I decided to write an extended syllabus for my Programming Languages and Paradigm course, which I am teaching again in the spring. I have been teaching this course for years, have detailed lecture notes for every session (plus many more), and already give students a syllabus that tries to explain in a useful way the purpose, goals, outcomes, and content of the course. That should give me a running start, right?

I've been working on putting my current syllabus's content into the extended syllabus format for several hours now. At this point, I have concluded that the process is three things: instructive, likely to be very helpful in the long run, and very hard to do.

Defining detailed goals and outcomes is instructive because it causes me to think about the course both at the highest level of detail (the goal of the course both in our curriculum and in our students' CS education) and at the lowest (what we want students our students to know and be able to do to when they leave the course). After teaching the course for many years, I tend to think big-picture thoughts about the course only at the beginning of the semester and only in an effort make general modifications to the direction it takes. Then I think about finer details on a unit-by-unit and session-by-session basis, slowly evolving the course content in reaction to specific stimuli. Looking at the course across multiple levels of abstraction at the same time is teaching me a lot about what my course is and does in a way that I don't usually see when I'm planning only at the high level or executing only at the day-to-day level.

One specific lesson I've learned is really a stark reminder of something I've always known: some of my sessions are chock-full of stuff: ideas, techniques, code, examples, .... That is great for exposing students to a wide swath of the programming languages world, but it is also a recipe for cognitive overload.

This process is helpful because it causes me think about concrete ways I can make the course better. I am finding holes in my coverage of certain topics and leaps from one concept to another that are intuitive in my mind but not documented anywhere.

I've been taking notes as I go long detailing specific changes I can make this spring:

  • to session materials, so that they give more examples of new concepts before I ask students to use the concepts in their work
  • to homework assignments, so that they emphasize specific goals of the course more clearly and to cover goals that seem to have lost coverage over time
  • to exams, so that they assess the outcomes we hope to achieve in the course
Designing class sessions, homework, and exams in terms of goals and outcomes creates a virtuous cycle in which the different elements of the course build on and reinforce one another. This is perhaps obvious to all you teachers out there, as it is to me, but it's easy to lose sight of over time.

But my most salient conclusion at this moment is that this is hard. It is difficult to explain the course in enough detail that faculty outside the area can grok the course as a part of our curriculum. It's difficult to explain the course in enough detail that other faculty could, at least in principle, teach it as designed. It's difficult to design a course carefully enough to be justifiably confident that it meets your goals for the course. That sounds a little like programming.

But I'm glad I'm doing it. It's worth the effort to design a course this carefully, and to re-visit the design periodically. That sounds a little like programming, too.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

December 26, 2016 8:38 AM

Learn By Programming

The latest edition of my compiler course has wrapped, with grades submitted and now a few days distance between us and the work. The course was successful in many ways, even though not all of the teams were all able to implement the entire compiler. That mutes the students' sense of accomplishment sometimes, but it's not unusual for at least some of the teams to have trouble implementing a complete code generator. A compiler is a big project. Fifteen weeks is not a lot of time. In that time, students learn a lot about compilers, and also about how to work as a team to build a big program using some of the tools of modern software development. In general, I was quite proud of the students' efforts and progress. I hope they were proud of themselves.

One of the meta-lessons students tend to learn in this course is one of the big lessons of any project-centered course:

... making something is a different learning experience from remembering something.

I think that a course like this one also helps most of them learn something else even more personal:

... the discipline in art-making is exercised from within rather than without. You quickly realize that it's your own laziness, ignorance, and sloppiness, not somebody else's bad advice, that are getting in your way. No one can write your [program] for you. You have to figure out a way to write it yourself. You have to make a something where there was a nothing.

"Laziness", "ignorance", and "sloppiness" seem like harsh words, but really they aren't. They are simply labels for weaknesses that almost all of us face when we first learn to create things on our own. Anyone who has written a big program has probably encountered them in some form.

I learned these lessons as a senior, too, in my university's two-term project course. It's never fun to come up short of our hopes or expectations. But most of us do it occasionally, and never more reliably than we are first learning how to make something significant. It is good for us to realize early on our own responsibility for how we work and what we make. It empowers us to take charge of our behavior.

Black Mountain College's Lake Eden campus

The quoted passages are, with the exception of the word "program", taken from Learn by Painting, a New Yorker article about "Leap Before You Look: Black Mountain College, 1933-1957", an exhibit at the Institute of Contemporary Art in Boston. Black Mountain was a liberal arts college with a curriculum built on top of an unusual foundation: making art. Though the college lasted less than a quarter century, its effects were felt across most of art disciplines in the twentieth century. But its mission was bigger: to educate citizens, not artists, through the making art. Making something is a different learning experience from remembering something, and BMC wanted all of its graduates to have this experience.

The article was a good read throughout. It closes with a comment on Black Mountain's vision that touches on computer science and reflects my own thinking about programming. This final paragraph begins with a slight indignity to us in CS but turns quickly into an admiration:

People who teach in the traditional liberal-arts fields today are sometimes aghast at the avidity with which undergraduates flock to courses in tech fields, like computer science. Maybe those students see dollar signs in coding. Why shouldn't they? Right now, tech is where value is being created, as they say. But maybe students are also excited to take courses in which knowing and making are part of the same learning process. Those tech courses are hands-on, collaborative, materials-based (well, virtual materials), and experimental -- a digital Black Mountain curriculum.

When I meet with prospective students and their parents, I stress that, while computer science is technical, it is not vocational. It's more. Many high school students sense this already. What attracts them to the major is a desire to make things: games and apps and websites and .... Earning potential appeals to some of them, of course, but students and parents alike seem more interested in something else that CS offers them: the ability to make things that matter in the modern world. They want to create.

The good news suggested in "Learn by Painting", drawing on the Black Mountain College experiment, is that learning by making things is more than just that. It is a different and, in most ways, more meaningful way to learn about the world. It also teaches you a lot about yourself.

I hope that at least a few of my students got that out of their project course with me, in addition to whatever they learned about compilers.


IMAGE. The main building of the former Black Mountain College, on the grounds of Camp Rockmont, a summer camp for boys. Courtesy of Wikipedia. Public domain.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

December 21, 2016 2:31 PM

Retaining a Sense of Wonder

A friend of mine recently shared a link to Radio Garden on a mailing list (remember those?), and in the ensuing conversation, another friend wrote:

I remember when I was a kid playing with my Dad's shortwave radio and just being flabbergasted when late one night I tuned in a station from Peru. Today you can get on your computer and communicate instantly with any spot on the globe, and that engenders no sense of wonder at all.

Such is the nature of advancing technology. Everyone becomes acclimated to amazing new things, and pretty soon they aren't even things any more.

Teachers face a particularly troublesome version of this phenomenon. Teach a subject for a few years, and pretty soon it loses its magic for you. It's all new to your students, though, and if you can let them help you see it through their eyes, you can stay fresh. The danger, though, is that it starts to look pretty ordinary to you, even boring, and you have a hard time helping them feel the magic.

If you read this blog much, you know that I'm pretty easy to amuse and pretty easy to make happy. Even so, I have to guard against taking life and computer science for granted.

Earlier this week, I was reading one reading one of the newer tutorials in Matthew Butterick's Beautiful Racket, Imagine a language: wires. In it, he builds a DSL to solve one of the problems in the 2015 edition of Advent of Code, Some Assembly Required. The problem is fun, specifying a circuit in terms of a small set of operations for wires and gates. Butterick's approach to solving it is fun, too: creating a DSL that treats the specification of a circuit as a program to interpret.

This is no big deal to a jaded old computer scientist, but remember -- or imagine -- what this solution must seem like to a non-computer scientist or to a CS student encountering the study of programming languages for the first time. With a suitable interpreter, every dataset is a program. If that isn't amazing enough, some wires datasets introduce sequencing problems, because the inputs to a gate are defined in the program after the gate. Butterick uses a simple little trick: define wires and gates as functions, not data. This simple little trick is really a big idea in disguise: Functions defer computation. Now circuit programs can be written in any order and executed on demand.

Even after all these years, computing's most mundane ideas can still astonish me sometimes. I am trying to keep my sense of wonder high and to renew it whenever it starts to flag. This is good for me, and good for my students.


P.S. As always, I recommend Beautiful Racket, and Matthew Butterick's work more generally, quite highly. He has a nice way of teaching useful ideas in a way that appreciates their beauty.

P.P.S. The working title of this entry was "Paging Louis C.K., Paging Louis C.K." That reference may be a bit dated by now, but still it made me smile.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

December 16, 2016 2:14 PM

Language and Thinking

Earlier this week, Rands tweeted:

Tinkering is a deceptively high value activity.

... to which I followed up:

Which is why a language that enables tinkering is a deceptively high value tool.

I thought about these ideas a couple of days later when I read The Running Conversation in Your Head and came across this paragraph:

The idea is not that you need language for thinking but that when language comes along, it sure is useful. It changes the way you think, it allows you to operate in different ways because you can use the words as tools.

This is how I think about programming in general and about new, and better, programming languages in particular. A programmer can think quite well in just about any language. Many of us cut our teeth in BASIC, and simply learning how to think computationally allowed us to think differently than we did before. But then we learn a radically different or more powerful language, and suddenly we are able to think new thoughts, thoughts we didn't even conceive of in quite the same way before.

It's not that we need the new language in order to think, but when it comes along, it allows us to operate in different ways. New concepts become new tools.

I am looking forward to introducing Racket and functional programming to a new group of students this spring semester. First-class functions and higher-order functions can change how students think about the most basic computations such as loops and about higher-level techniques such as OOP. I hope to do a better job this time around helping them see the ways in which it really is different.

To echo the Running Conversation article again, when we learn a new programming style or language, "Something really special is created. And the thing that is created might well be unique in the universe."

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 12, 2016 3:15 PM

Computer Science Is Not That Special

I'm reminded of a student I met with once who told me that he planned to go to law school, and then a few minutes later, when going over a draft of a lab report, said "Yeah... Grammar isn't really my thing." Explaining why I busted up laughing took a while.

When I ask prospective students why they decided not to pursue a CS degree, they often say things to the effect of "Computer science seemed cool, but I heard getting a degree in CS was a lot of work." or "A buddy of mine told me that programming is tedious." Sometimes, I meet these students as they return to the university to get a second degree -- in computer science. Their reasons for returning vary from the economic (a desire for better career opportunities) to personal (a desire to do something that they have always wanted to do, or to pursue a newfound creative interest).

After you've been in the working world a while, a little hard work and some occasional tedium don't seem like deal breakers any more.

Such conversations were on my mind as I read physicist Chad Orzel's recent Science Is Not THAT Special. In this article, Orzel responds to the conventional wisdom that becoming a scientist and doing science involve a lot of hard work that is unlike the exciting stuff that draws kids to science in the first place. Then, when kids encounter the drudgery and hard work, they turn away from science as a potential career.

Orzel's takedown of this idea is spot on. (The quoted passage above is one of the article's lighter moments in confronting the stereotype.) Sure, doing science involves a lot of tedium, but this problem is not unique to science. Getting good at anything requires a lot of hard work and tedious attention to detail. Every job, every area of expertise, has its moments of drudgery. Even the rare few who become professional athletes and artists, with careers generally thought of as dreams that enable people to earn a living doing the thing they love, spend endless hours engaged in the drudgery of practicing technique and automatizing physical actions that become their professional vocabulary.

Why do we act as if science is any different, or should be?

Computer science gets this rap, too. What could be worse than fighting with a compiler to accept a program while you are learning to code? Or plowing threw reams of poorly documented API descriptions to plug your code into someone's e-commerce system?

Personally, I can think of lots of things that are worse. I am under no illusion, however, that other professionals are somehow shielded from such negative experiences. I just prefer my pains to theirs.

Maybe some people don't like certain kinds of drudgery. That's fair. Sometimes we gravitate toward the things whose drudgery we don't mind, and sometimes we come to accept the drudgery of the things we love to do. I'm not sure which explains my fascination with programming. I certainly enjoy the drudgery of computer science more than that of most other activities -- or at least I suffer it more gladly.

I'm with Orzel. Let's be honest with ourselves and our students that getting good at anything takes a lot of hard work and, once you master something, you'll occasionally face some tedium in the trenches. Science, and computer science in particular, are not that much different from anything else.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

December 09, 2016 1:54 PM

Two Quick Hits with a Mathematical Flavor

I've been wanting to write a blog entry or two lately about my compiler course and about papers I've read recently, but I've not managed to free up much time as semester winds down. That's one of the problems with having Big Ideas to write about: they seem daunting and, at the very least, take time to work through.

So instead here are two brief notes about articles that crossed my newsfeed recently and planted themselves in my mind. Perhaps you will enjoy them even without much commentary from me.

A Student's Unusual Proof Might Be A Better Proof

I asked a student to show that between any two rationals is a rational.

She did the following: if x < y are rational then take δ << y-x and rational and use x+δ.

I love the student's two proofs in article! Student programmers are similarly creative. Their unusual solutions often expose biases in my thinking and give me way to think about a problem. If nothing else, they help to understand better how students think about ideas that I take for granted.

Numberless Word Problems

Some girls entered a school art competition. Fewer boys than girls entered the competition.

She projected her screen and asked, "What math do you see in this problem?"

Pregnant pause.

"There isn't any math. There aren't any numbers."

I am fascinated by the possibility of adapting this idea to teaching students to think like a programmer. In an intro course, for example, students struggle with computational ideas such as loops and functions even though they have a lot of experience with these ideas embodied in their daily lives. Perhaps the language we use gets in the way of them developing their own algorithmic skills. Maybe I could use computationless word problems to get them started?

I'm giving serious thought to ways I might use this approach to help students learn functional programming in my Programming Languages course this spring. The authors describes how to write numberless word problems, and I'm wondering how I might bring the philosophy to computer science. If you have any ideas, please share!

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Teaching and Learning

December 05, 2016 2:42 PM

Copying Interfaces, Copying Code

Khoi Vinh wrote a short blog entry called The Underestimated Merits of Copying Someone Else's Work that reminds us how valuable copying others' work, a standard practice in the arts, can be. At the lowest level there is copying at the textual level. Sometimes, the value is mental or mechanical:

Hunter S. Thompson famously re-typed, word for word, F. Scott Fitzgerald's "The Great Gatsby" just to learn how it was done.

This made me think back to the days when people typed up code they found in Byte magazine and other periodicals. Of course, typing a program gave you more than practice typing or a sense of what it was like to type that much; it also gave you a working program that you could use and tinker with. I don't know if anyone would ever copy a short story or novel by hand so that they could morph it into something new, but we can do that meaningfully with code.

I missed the "copy code from Byte" phase of computing. My family never had a home computer, and by the time I got to college and changed my major to CS, I had plenty of new programs to write. I pulled ideas about chess-playing programs and other programs I wanted to write from books and magazines, but I never typed up an entire program's source code. (I mention one of my first personal projects in an old OOPSLA workshop report.)

I don't hear much these days about people copying code keystroke for keystroke. Zed Shaw has championed this idea in a series of introductory programming books such as Learn Python The Hard Way. There is probably something to be learned by copying code Hunter Thompson-style, feeling the rhythm of syntax and format by repetition, and soaking up semantics along the way.

Vinh has a more interesting sort of copying in mind, though: copying the interface of a software product:

It's odd then to realize that copying product interfaces is such an uncommon learning technique in design. ... it's even easier to re-create designs than it is to re-create other forms of art. With a painting or sculpture, it's often difficult to get access to the historically accurate tools and materials that were used to create the original. With today's product design, the tools are readily available; most of us already own the exact same software employed to create any of the most prominent product designs you could name.

This idea generalizes beyond interfaces to any program for which we don't have source code. We often talk about reverse engineering a program, but in my experience this usually refers to creating a program that behaves "just like" the original. Copying an interface pixel by pixel, like copying a program or novel character by character, requires the artist to attend to the smallest details -- to create an exact replica, not a similar work.

We cannot reverse engineer a program and arrive at identical source code, of course, but we can try to replicate behavior and interface exactly. Doing so might help a person appreciate the details of code more. Such a practice might even help a programmer learn the craft of programming in a different way.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

November 27, 2016 10:26 AM

Good Teaching Is Grounded In Generosity Of Spirit

In My Writing Education: A Time Line, George Saunders recounts stories of his interactions with writing teachers over the years, first in the creative writing program at Syracuse and later as a writer and teacher himself. Along the way, he shows us some of the ways that our best teachers move us.

Here, the teacher gets a bad review:

Doug gets an unkind review. We are worried. Will one of us dopily bring it up in workshop? We don't. Doug does. Right off the bat. He wants to talk about it, because he feels there might be something in it for us. The talk he gives us is beautiful, honest, courageous, totally generous. He shows us where the reviewer was wrong -- but also where the reviewer might have gotten it right. Doug talks about the importance of being able to extract the useful bits from even a hurtful review: this is important, because it will make the next book better. He talks about the fact that it was hard for him to get up this morning after that review and write, but that he did it anyway. He's in it for the long haul, we can see.

I know some faculty who basically ignore student assessments of their teaching. They paid attention for a while at the beginning of their careers, but it hurt too much, so they stopped. Most of the good teachers I know, though, approach their student assessments the way that Doug approaches his bad review: they look for the truths in the reviews, take those truths seriously, and use them to get better. Yes, a bad set of assessments hurts. But if you are in it for the long haul, you get back to work.

Here, the teacher gives a bad review:

What Doug does for me in this meeting is respect me, by declining to hyperbolize my crap thesis. I don't remember what he said about it, but what he did not say was, you know: "Amazing, you did a great job, this is publishable, you rocked our world with this! Loved the elephant." There's this theory that self-esteem has to do with getting confirmation from the outside world that our perceptions are fundamentally accurate. What Doug does at this meeting is increase my self-esteem by confirming that my perception of the work I'd been doing is fundamentally accurate. The work I've been doing is bad. Or, worse: it's blah. This is uplifting -- liberating, even -- to have my unspoken opinion of my work confirmed. I don't have to pretend bad is good. This frees me to leave it behind and move on and try to do something better. The main thing I feel: respected.

Sometimes, students make their best effort but come up short. They deserve the respect of an honest review. Honest doesn't have to be harsh; there is a difference between being honest and being a jerk. Sometimes, students don't make their best effort, and they deserve the respect of an honest review, too. Again, being honest doesn't mean being harsh. In my experience, most students appreciate an honest, objective review of their work. They almost always know when they are coming up short, or when they aren't working hard enough. When a teacher confirms that knowledge, they are freed -- or motivated in a new way -- to move forward.

Here, the teacher reads student work:

I am teaching at Syracuse myself now. Toby, Arthur Flowers, and I are reading that year's admissions materials. Toby reads every page of every story in every application, even the ones we are almost certainly rejecting, and never fails to find a nice moment, even when it occurs on the last page of the last story of a doomed application. "Remember that beautiful description of a sailboat on around page 29 of the third piece?" he'll say. And Arthur and I will say: "Uh, yeah ... that was ... a really cool sailboat." Toby has a kind of photographic memory re stories, and such a love for the form that goodness, no matter where it's found or what it's surrounded by, seems to excite his enthusiasm. Again, that same lesson: good teaching is grounded in generosity of spirit.

It has taken me a long time as a teacher to learn to have Toby's mindset when reading student work, and I'm still learning. Over the last few years, I've noticed myself trying more deliberately to find the nice moments in students' programs, even the bad ones, and to tell students about them. That doesn't mean being dishonest about the quality of the overall program. But nice moments are worth celebrating, wherever they are found. Sometimes, those are precisely the elements students need to hear about, because they are the building blocks for getting better.

Finally, here is the teacher talking about his own craft:

During the Q&A someone asks what Toby would do if he couldn't be a writer.
A long, perplexed pause.
"I would be very sad", he finally says.

I like teaching computer science, but what has enabled me to stay in the classroom for so many years and given me the stamina to get better at teaching is that I like doing computer science. I like to program. I like to solve problems. I like to find abstractions and look for ways to solve other problems. There are many things I could do if I were not a computer scientist, but knowing what I know now, I would be a little sad.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

November 20, 2016 10:17 AM

Celebrating a Friend's Success

Wade Arnold accepting the Young Alumni Award from UNI President Jim Wohlpart

Last week, I read a blog entry by Ben Thompson that said Influence lives at intersections. Thompson was echoing a comment about Daniel Kahneman's career: "Intellectual influence is the ability to dissolve disciplinary boundaries." These were timely references for my week.

On Friday night, I had the pleasure of attending the Heritage Honours Awards, an annual awards dinner hosted by my university's alumni association. One of our alumni, Wade Arnold, received the Young Alumni Award for demonstrated success early in a career. I mentioned Wade in a blog entry several years ago, when he and I spoke together at a seminar on interactive digital technologies. That day, Wade talked about intersections:

It is difficult to be the best at any one thing, but if you are very good at two or three or five, then you can be the best in a particular market niche. The power of the intersection.

Wade built his company, Banno, by becoming very good at several things, including functional programming, computing infrastructure, web development, mobile development, and financial technology. He was foresightful and lucky enough to develop this combination of strengths before most other people did. Most important, though, he worked really hard to build his company: a company that people wanted to work with, and a company that people wanted to work for. As a result, he was able to grow a successful start-up in a small university town in the middle of the country.

It's been a delight for me to know Wade all these years and watch him do his thing. I'll bet he has some interesting ideas in store for the future.

The dinner also provided me with some unexpected feelings. Several times over the course of the evening, someone said, "Dr. Wallingford -- I feel like I know you." I had the pleasure of meeting Wade's parents, who said kind things about my influence on their son. Even his nine-year-old son said, "My dad was talking about you in the car on the drive over." No one was confused about whom we were there to honor Friday night, about who had done the considerable work to build himself into an admirable man and founder. That was all Wade. But my experience that night is a small reminder to all you teachers out there: you do have an effect on people. It was certainly a welcome reminder for me at the end of a trying semester.

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

October 22, 2016 2:00 PM

Competence and Creating Conditions that Minimize Mistakes

I enjoyed this interview with Atul Gawande by Ezra Klein. When talking about making mistakes, Gawande notes that humans have enough knowledge to cut way down on errors in many disciplines, but we do not always use that knowledge effectively. Mistakes come naturally from the environments in which we work:

We're all set up for failure under the conditions of complexity.

Mistakes are often more a matter of discipline and attention to detail than a matter of knowledge or understanding. Klein captures the essence of Gawande's lesson in one of his questions:

We have this idea that competence is not making mistakes and getting everything right. [But really...] Competence is knowing you will make mistakes and setting up a context that will help reduce the possibility of error but also help deal with the aftermath of error.

In my experience, this is a hard lesson for computer science students to grok. It's okay to make mistakes, but create conditions where you make as few as possible and in which you can recognize and deal with the mistakes as quickly as possible. High-discipline practices such as test-first and pair programming, version control, and automated builds make a lot more sense when you see them from this perspective.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Software Development, Teaching and Learning

October 17, 2016 4:10 PM

Using Programming to Learn Math, Even at the University

There is an open thread on the SIGCSE mailing list called "Forget the language wars, try the math wars". Faculty are discussing how to justify math requirements on a CS major, especially for students who "just want to be programmers". Some people argue that math requirements are a barrier to recruiting students who can succeed in computer science, in particular calculus.

Somewhere along the line, Cay Horstmann wrote a couple of things I agree with. First, he said that he didn't want to defend the calculus requirement because most calculus courses do not teach students how to think "but how to follow recipes". I have long had this complaint about calculus, especially as it's taught in most US high schools and universities. Then he wrote something more positive:

What I would like to see is teaching math alongside with programming. None of my students were able to tell me what sine and cosine were good for, but when they had to program a dial [in a user interface], they said "oh".

Couldn't that "oh" have come earlier in their lives? Why don't students do programming in middle school math? I am not talking large programs--just a few lines, so that they can build models and intuition.

I agree wholeheartedly. And even if students do not have such experiences in their K-12 math classes, the least we could do help them have that "oh" experience earlier in their university studies.

My colleagues and I have been discussing our Discrete Structures course now for a few weeks, including expected outcomes, its role as a prerequisite to other courses, and how we teach it. I have suggested that one of the best ways to learn discrete math is to connect it with programs. At our university, students have taken at least one semester of programming (currently, in Python) before they take Discrete. We should use that to our advantage!

A program can help make an abstract idea concrete. When learning about set operations, why do only paper-and-pencil exercises when you can use simple Python expressions in the REPL? Yes, adding programming to the mix creates new issues to deal with, but if designed well, such instruction could both improve students' understanding of discrete structures -- as Horstmann says, helping them build models and intuition -- and give students more practice writing simple programs. An ancillary benefit might be to help students see that computer scientists can use computation to help them learn new things, thus preparing for habits that can extend to wider settings.

Unfortunately, the most popular Discrete Structures textbooks don't help much. They do try to use CS-centric examples, but they don't seem otherwise to use the fact that students are CS majors. I don't really blame them. They are writing for a market in which students study many different languages in CS 1, so they can't (and shouldn't) assume any particular programming language background. Even worse, the Discrete Structures course appears at different places throughout the CS curriculum, which means that textbooks can't assume even any particular non-language CS experience.

Returning to Horstmann's suggestion to augment math instruction with programming in K-12, there is, of course, a strong movement nationally to teach computer science in high school. My state has been disappointingly slow to get on board, but we are finally seeing action. But most of the focus in this nationwide movement is on teaching CS qua CS, with less interest in emphasis on integrating CS into math and other core courses.

For this reason, let us again take a moment to thank the people behind the Bootstrap project for leading the charge in this regard, helping teachers use programming in Racket to teach algebra and other core topics. They are even evaluating the efficacy of the work and showing that the curriculum works. This may not surprise us in CS, but empirical evidence of success is essential if we hope to get teacher prep programs and state boards of education to take the idea seriously.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

September 25, 2016 9:40 AM

There Is Only One Culture, But Two Languages

W.H. Auden, in A Certain World, on the idea of The Two Cultures:

Of course, there is only one. Of course, the natural sciences are just as "humane" as letters. There are, however, two languages, the spoken verbal language of literature, and the written sign language of mathematics, which is the language of science. This puts the scientist at a great advantage, for, since like all of us he has learned to read and write, he can understand a poem or a novel, whereas there are very few men of letters who can understand a scientific paper once they come to the mathematical parts.

When I was a boy, we were taught the literary languages, like Latin and Greek, extremely well, but mathematics atrociously badly. Beginning with the multiplication table, we learned a series of operations by rote which, if remembered correctly, gave the "right" answer, but about any basic principles, like the concept of number, we were told nothing. Typical of the teaching methods then in vogue is the mnemonic which I had to learn.
Minus times Minus equals Plus:
The reason for this we need not discuss.

Sadly, we still teach young people that it's okay if math and science are too hard to master. They grow into adults who feel a chasm between "arts and letters" and "math and science". But as Auden notes rightly, there is no chasm; there is mostly just another language to learn and appreciate.

(It may be some consolation to Auden that we've reached a point where most scientists have to work to understand papers written by scientists in other disciplines. They are written in highly specialized languages.)

In my experience, it is more acceptable for a humanities person to say "I'm not a science person" or "I don't like math" than for a scientist to say something similar about literature, art, or music. The latter person is thought, silently, to be a Philistine; the former, an educated person with a specialty.

I've often wondered if this experience suffers from observation bias or association bias. It may well. I certainly know artists and writers who have mastered both languages and who remain intensely curious about questions that span the supposed chasm between their specialties and mine. I'm interested in those questions, too.

Even with this asymmetry, the presumed chasm between cultures creates low expectations for us scientists. Whenever my friends in the humanities find out that I've read all of Kafka's novels and short stories; that Rosencrantz and Guildenstern Are Dead is my favorite play, or that I even have a favorite play; that I really enjoyed the work of choreographer Merce Cunningham; that my office bookshelf includes the complete works of William Shakespeare and a volume of William Blake's poetry -- I love the romantics! -- most seem genuinely surprised. "You're a computer scientist, right?" (Yes, I like Asimov, Heinlein, Clarke, and Bradbury, too.)

Auden attributes his illiteracy in the language of mathematics and science to bad education. The good news is that we can reduce, if not eliminate, the language gap by teaching both languages well. This is a challenge for both parents and schools and will take time. Change is hard, especially when it involves the ways we talk about the world.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

September 18, 2016 3:49 PM

Talking Shop

a photo of the Blueridge Orchard, visited by cyclists on the Cedar Valley Farm Ride

I agree with W.H. Auden:

Who on earth invented the silly convention that it is boring or impolite to talk shop? Nothing is more interesting to listen to, especially if the shop is not one's own.

My wife went on a forty-mile bike ride this morning, a fundraiser for the Cedar Valley Bicycle Collective, which visited three local farms. At those stops, I had the great fortune to listen to folks on all three farms talk shop. We learned about making ice cream and woodcarving at Three Pines Farm. We learned about selecting, growing, and picking apples -- and the damage hail and bugs can do -- at Blueridge Orchard. And the owner of the Fitkin Popcorn Farm talked about the popcorn business. He showed us the machines they use to sort the corn out of the field, first by size and then by density. He also talked about planting fields, harvesting the corn, and selling the product nationally. I even learned that we can pop the corn while it's still on the ears! (This will happen in my house very soon.)

I love to listen to people talk shop. In unguarded moments, they speak honestly about something they love and know deeply. They let us in on what it is like for them to work in their corner of the world. However big I try to make my world, there is so much more out there to learn.

The Auden passage is from his book A Certain World, a collage of poems, quotes, and short pieces from other writers with occasional comments of his own. Auden would have been an eclectic blogger! This book feels like a Tumblr blog, without all the pictures and 'likes'. Some of the passages are out of date, but they let us peak in on the mind of an accomplished poet. A little like good shop talk.

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

September 02, 2016 4:12 PM

Be Open to What Students Think -- For Real

On the first day of my compiler class this fall, I had my students fill out a short survey to help me set the stage for the course. After I asked them to list the the three or four programming languages they know best, I asked them:

  • Based on your experience using these languages, list them in order from easiest to use to hardest to use.
  • Given what you know about them, list these languages in order from easiest to compile to hardest to compile.
We then used their answers to unpack what "easy" and "hard" mean in these contexts, and what it would mean even to be answer these questions.

While they were completing the survey, one student raised his hand and asked, "When you easy or hard to compile, do you mean for the programmer or the compiler?" I laughed almost immediately.

Fortunately, I've had all these students in class before, and they know that I'm not a mean-spirited person. Even so, I just as quickly apologized for laughing and let him know that I wasn't laughing at the question so much as laughing at my own surprise: It had never occurred to me that someone might interpret the question in that way!

I realized, though, that from a student's perspective, getting a Python program to the point of runnability is a very different thing from getting, say, a Java or Ada program to the point of runnability. For a beginner, to get his or her first few Ada programs to compile is indeed a chore. I remember feeling the same way when I learned Haskell as a relatively experienced professor and programmer, many years after I had last been a student in a classroom.

This story came to mind as I read Required Reading for Math Teachers this morning. It's actually pretty good reading for teachers of any subject. Toward the end of the post, the author reminds us that it helps for teachers to be legitimately open to students' thought processes, whether or not they think what we think they should be thinking. In fact, those are precisely the moments when we want to be most open to what they are thinking. These are the moments that help us to diagnose errors in their thinking -- and in ours.

This passage resonated with my experience:

I have throughout my career been repeatedly surprised by the discovery that nearly every time a student offers an idea authentically (i.e. not as just a random guess), it makes some sort of sense. Maybe not complete sense, and maybe it's not at all where I was headed. But if I can curb my initial reaction of "this kid is totally confused" long enough to actually take in the train of thought, there is almost uniformly some worthwhile reasoning inside it. Then even if I need to say "we're going to stick to the topic", I can do so after acknowledging the reasoning.

Acknowledging students' ideas and thinking is a matter of basic respect, but it also plays a big role in the environment we create in our classes. I hope that I have been respectful and open enough with these students in the past that my question-asker could trust that I wan't mocking him and that I was genuinely surprised. We all learned something that day.

As that blog post goes on to say, we have to make sure that the questions we ask students are legitimate questions. We communicate this intention by acknowledging people when they treat our questions as legitimate. We teachers need to treat our student's questions the same way.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

August 30, 2016 3:36 PM

Things People Should Know About Being a Teacher

In 7 things I wish people understood about being a teacher, Andrew Simmons captures a few of the things that make teaching so rewarding and so challenging. If you don't understand these truths, you may not understand why anyone would want to teach. You also run the risk of misunderstanding the problems with our education system and thus supporting changes that are unlikely to fix them. Check it out.

Even though Simmons writes of teaching high school, most of what he says applies just as well to university professors. I especially liked this comment, on what software developers call sustainable pace

... would-be superteachers are smart, sometimes masochistic 23-year-olds working 18-hour days to pump up test scores for a few years before moving on to administrative positions, law school, or nervous breakdowns. They embrace an unsustainable load.

I used to wonder why so many good teachers ended up leaving the classroom. One reason is burn-out. Universities burn out researchers and teachers alike by pushing them onto a treadmill, or by letting them get on and stay there of their own volition. Good teaching can happen every year, if we learn how to maintain balance.

My favorite line of the article, though, is this gem:

Everything I learn is filtered through the possibility that it might be taught.

When I read that line, I nodded my head silently. This guy really is a teacher.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

August 21, 2016 10:23 AM

Parnas and Software Patterns

Earlier this week, I tweeted a paraphrase of David Parnas that a few people liked:

Parnas observes: "Professional Engineers rarely use 'engineer' as a verb." And it's not because they are busy 'architecting' systems.

The paraphrase comes from Parnas's On ICSE's "Most Influential" Papers, which appears in the July 1995 issue so ACM SIGSOFT's Software Engineering Notes. He wrote that paper in conjunction with his acceptance speech on receiving the Most Influential Paper award at ICSE 17. It's a good read on how the software engineering research community's influence was, at least at that time, limited to other researchers. Parnas asserts that researchers should strive to influence practitioners, the people who are actually writing software.

Why doesn't software engineering research influence practitioners? It's simple:

Computer professionals do not read our literature because it does not help them to do their job better.

In a section called "We are talking to ourselves", Parnas explains why the software engineering literature fails to connect with people who write software:

Most of our papers are written in the tradition of science, not engineering. We write up the results of our research for readers who are also researchers, not for practitioners. We base our papers on previous work done by other researchers, and often ignore current practical problems. In many other engineering fields, the results of research are reported in "How to" papers. Our papers are "This is what I did" papers. We describe our work, how our work differs from other people's work, what we will do next, etc. This is quite appropriate for papers directed to other researchers, but it is not what is needed in papers that are intended to influence practitioners. Practitioners are far more interested in being told the basic assumptions behind the work, than in knowing how this work differs from the work by the author's cohorts in the research game.

Around the time Parnas wrote this article and gave his acceptance speech at ICSE 17, the Pattern Languages of Programs conferences were taking off, with a similar motivation: to create a literature by and for software practitioners. Patterns describe how to create programs in practical terms. They describe techniques, but also the context in which they work, the forces that make them more and less applicable, and the patterns you can use to address the issues that arise after you the technique. The community encouraged writing in a straightforward style, using the vocabulary of professional developers.

At the early PLoP conferences, you could feel the tension between practitioners and academics, some of which grew out of the academic style of writing and the traditions of the scientific literature. I had to learn a lot about how to write for an audience of software developers. Fortunately, the people in the PLoP community took the time to help me get better. I have fond memories of receiving feedback from Frank Buschman, Peter Sommerlad, Ralph Johnson, Ward Cunningham, Kyle Brown, Ken, Auer, and many others. The feedback wasn't always easy to internalize -- it's hard to change! -- but it was necessary.

I'm not sure that an appreciably larger number of academics in software engineering and computer science more broadly write for the wider community of software practitioners these days than when Parnas made his remarks. There are certainly more venues available to us from patterns-related conferences, separate tracks at conferences like SPLASH, and blogs. Unfortunately, the academic reward structure isn't always friendly to this kind of writing, especially early in one's career. Some universities have begun to open up their definition of scholarship, though, which creates new opportunities.

At their best, software patterns are exactly what Parnas calls for: creating a how-to literature aimed at practitioners. Researchers and practitioners can both participate in this endeavor.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Teaching and Learning

August 14, 2016 10:55 AM

Hemingway on Teachers, While Teaching

Ernest Hemingway sitting on a dock next to his boat, Pilar, in the 1930s

Early in Arnold Samuelson's With Hemingway: A Year in Key West and Cuba, Papa is giving an impromptu lecture about writing to two aspiring young writers. (He does that a lot in the book, whenever the men are out sailing and fishing.) This particular lecture was prompted by what he thought was bad advice in a book by a successful pulp fiction author on how to get started as a writer. An earlier session had focused on the shortcomings of going to college to learn how to become a writer.

Toward the end of his discourse, Hemingway tells the young writers to do daily writing exercise and generously offers to read read their work, giving feedback on how to get better. This offer elicits a few more remarks about the idea of college writing professors:

"They ought to have me teach some of those college classes. I could teach them something. Most professors of English composition can tell the students what's wrong with their pieces but they don't know how to make them good, because, if they knew that, they'd be writers themselves and they wouldn't have to teach."

"What do you think of the life of a professor?"

"All right for a person who is vain and likes to have the adulation of his students. Well, now, do you fellows think you can remember everything Professor Hemingway has told you? Are you prepared for a written examination on the lecture?"

Teaching computer science must be different from teaching fiction writing. I have been teaching for quite a few years now and have never received any adulation. Then again, though, I've never experienced much derision either. My students seems to develop a narrower set of emotions. Some seem to like me quite a bit and look for chances to take another course with me. Other students are... indifferent. To them, I'm just the guy standing in the way of them getting to somewhere else they want to be.

Hemingway's "have to teach" dig is cliché. Perhaps the Ernest Hemingways and Scott Fitzgeralds of the world should be devoting all of their time to writing, but there have a been any number of excellent authors who have supplemented their incomes and filled the down time between creative bursts by helping other writers find a path for themselves. Samuelson's book itself is a testament to how much Papa loved to share his wisdom and to help newcomers find their footing in a tough business. During all those hours at sea, Hemingway was teaching.

Still, I understand what Hemingway means when he speaks of the difference between knowing that something is bad and knowing how to make something good. One of the biggest challenges I faced in my early years as a professor was figuring out how to go beyond pointing out errors and weaknesses in my students' code to giving them concrete advice on how two design and write good programs. I'm still learning how to do that.

I'm lucky that I like to write programs myself. Writing code and learning new styles and languages is the only way to stay sharp. Perhaps if I were really good, I'd leave academia and build systems for Google or some hot start-up, as Hemingway would have it. I'm certainly under no illusion that I can simulate that kind of experience working at a university. But I do think a person can both do and teach, and that the best teachers are ones who take both seriously. In computer science, it is a constant challenge to keep up with students who are pushing ahead into a world that keeps changing.


The photo above comes from the John F. Kennedy Presidential Library and Museum. It shows Hemingway sitting on a dock next to his boat, Pilar, sometime in the 1930s. The conversation quoted above took place on the Pilar in 1934.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

August 07, 2016 10:36 AM

Some Advice for How To Think, and Some Personal Memories

I've been reading a bunch of the essays on David Chapman's Meaningness website lately, after seeing a link to one on Twitter. (Thanks, @kaledic.) This morning I read How To Think Real Good, about one of Chapman's abandoned projects: a book of advice for how to think and solve problems. He may never write this book as he once imagined it, but I'm glad he wrote this essay about the idea.

First of all, it was a fun read, at least for me. Chapman is a former AI researcher, and some of the stories he tells remind me of things I experienced when I was in AI. We were even in school at about the same time, though in different parts of the country and different kinds of program. His work was much more important than mine, but I think at some fundamental level most people in AI share common dreams and goals. It was fun to listen as Chapman reminisced about knowledge and AI.

He also introduced me to the dandy portmanteau anvilicious. I keep learning new words! There are so many good ones, and people make up the ones that don't exist already.

My enjoyment was heightened by the fact that the essay stimulated the parts of my brain that like to think about thinking. Chapman includes a few of the heuristics that he intended to include in his book, along with anecdotes that illustrate or motivate them. Here are three:

All problem formulations are "false", because they abstract away details of reality.

Solve a simplified version of the problem first. If you can't do even that, you're in trouble.

Probability theory is sometimes an excellent way of dealing with uncertainty, but it's not the only way, and sometimes it's a terrible way.

He elaborates on the last of these, pointing out that probability theory tends to collapse many different kinds of uncertainty into a single value. This does not work all that well in practice, because different kinds of uncertainty often need to be handles in very different ways.

Chapman has a lot to say about probability. This essay was prompted by what he sees as an over-reliance of the rationalist community on a pop version of Bayesianism as its foundation for reasoning. But as an old AI researcher, he knows that an idea can sound good and fail in practice for all sorts of reasons. He has also seen how a computer program can make clear exactly what does and doesn't work.

Artificial intelligence has always played a useful role as a reality check on ideas about mind, knowledge, reasoning, and thought. More generally, anyone who writes computer programs knows this, too. You can make ambiguous claims with English sentences, but to write a program you really have to have a precise idea. When you don't have a precise idea, your program itself is a precise formulation of something. Figuring out what that is can be a way of figuring out what you were really thing about in the first place.

This is one of the most important lessons college students learn from their intro CS courses. It's an experience that can benefit all students, not just CS majors.

Chapman also includes a few heuristics for approaching the problem of thinking, basically ways to put yourself in a position to become a better thinker. Two of my favorites are:

Try to figure out how people smarter than you think.

Find a teacher who is willing to go meta and explain how a field works, instead of lecturing you on its subject matter.

This really is good advice. Subject matter is much easier to come by than deep understanding of how the discipline work, especially in these days of the web.

The word meta appears frequently throughout this essay. (I love that the essay is posted on the metablog/ portion of his site!) Chapman's project is thinking about thinking, a step up the ladder of abstraction from "simply" thinking. An AI program must reason; an AI researcher must reason about how to reason.

This is the great siren of artificial intelligence, the source of its power and also its weaknesses: Anything you can do, I can do meta.

I think this gets at why I enjoyed this essay so much. AI is ultimately the discipline of applied epistemology, and most of us who are lured into AI's arms share an interest in what it means to speak of knowledge. If we really understand knowledge, then we ought to be able to write a computer program that implements that understanding. And if we do, how can we say that our computer program isn't doing essentially the same thing that makes us humans intelligent?

As much as I love computer science and programming, my favorite course in graduate school was an epistemology course I took with Prof. Rich Hall. It drove straight to the core curiosity that impelled me to study AI in the first place. In the first week of the course, Prof. Hall laid out the notion of justified true belief, and from there I was hooked.

A lot of AI starts with a naive feeling of this sort, whether explicitly stated or not. Doing AI research brings that feeling into contact with reality. Then things gets serious. It's all enormously stimulating.

Ultimately Chapman left the field, disillusioned by what he saw as a fundamental limitation that AI's bag of tricks could never resolve. Even so, the questions that led him to AI still motivate him and his current work, which is good for all of us, I think.

This essay brought back a lot of pleasant memories for me. Even though I, too, am no longer in AI, the questions that led me to the field still motivate me and my interests in program design, programming languages, software development, and CS education. It is hard to escape the questions of what it means to think and how we can do it better. These remain central problems of what it means to be human.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Teaching and Learning

July 28, 2016 2:37 PM

Functional Programming, Inlined Code, and a Programming Challenge

an example of the cover art for the Commander Keen series of games

I recently came across an old entry on Jonathan Blow's blog called John Carmack on Inlined Code. The bulk of the entry consists an even older email message that Carmack, lead programmer on video games such as Doom and Quake, sent to a mailing list, encouraging developers to consider inlining function calls as a matter of style. This email message is the earliest explanation I've seen of Carmack's drift toward functional programming, seeking to as many of its benefits as possible even in the harshly real-time environment of game programming.

The article is a great read, with much advice borne in the trenches of writing and testing large programs whose run-time performance is key to their success. Some of the ideas involve programming language:

It would be kind of nice if C had a "functional" keyword to enforce no global references.

... while others are more about design style:

The function that is least likely to cause a problem is one that doesn't exist, which is the benefit of inlining it.

... and still others remind us to rely on good tools to help avoid inevitable human error:

I now strongly encourage explicit loops for everything, and hope the compiler unrolls it properly.

(This one may come in handy as I prepare to teach my compiler course again this fall.)

This message-within-a-blog-entry itself quotes another email message, by Henry Spencer, which contains the seeds of a programming challenge. Spencer described a piece of flight software written in a particularly limiting style:

It disallowed both subroutine calls and backward branches, except for the one at the bottom of the main loop. Control flow went forward only. Sometimes one piece of code had to leave a note for a later piece telling it what to do, but this worked out well for testing: all data was allocated statically, and monitoring those variables gave a clear picture of most everything the software was doing.

Wow: one big loop, within which all control flows forward. To me, this sounds like a devilish challenge to take on when writing even a moderately complex program like a scanner or parser, which generally contain many loops within loops. In this regard, it reminds me of the Polymorphism Challenge's prohibition of if-statements and other forms of selection in code. The goal of that challenge was to help programmers really grok how the use of substitutable objects can lead to an entirely different style of program than we tend to create with traditional procedural programming.

Even though Carmack knew that "a great deal of stuff that goes on in the aerospace industry should not be emulated by anyone, and is often self destructive", he thought that this idea might have practical value, so he tried it out. The experience helped him evolve his programming style in a promising direction. This is a great example of the power of the pedagogical pattern known as Three Bears: take an idea to its extreme in order to learn the boundaries of its utility. Sometimes, you will find that those boundaries lie beyond what you originally thought.

Carmack's whole article is worth a read. Thanks to Jonathan Blow for preserving it for us.


The image above is an example of the cover art for the "Commander Keen" series of video games, courtesy of Wikipedia. John Carmack was also the lead programmer for this series. What a remarkable oeuvre he has produced.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Patterns, Software Development, Teaching and Learning

July 27, 2016 10:58 AM

Teaching Programming Versus Teaching Art

Like many people, I am fond of analogies between software development and arts like writing and painting. It's easy to be seduced by similarities even when the daily experiences of programmers and artists are often so different.

For that reason, I was glad that this statement by sculptor Jacques Lipschutz stood out in such great relief from the text around it:

Teaching is death. If he teaches, the sculptor has to open up and reveal things that should be closed and sacred.

For me, teaching computer science has been just the opposite. Teaching forces me to open up my thinking processes. It encourages me to talk with professional developers about how they do what they do and what they think about along the way. Through these discussions, we do reveal things that sometimes feel almost sacred, but I think we all benefit from the examination. It not only helps me to teach novice developers more effectively; it also helps me to be a better programmer myself.


(The Lipschutz passage comes from Conversations with Artists, which I quoted for the first time last week.)

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

July 22, 2016 11:02 AM

What Happens When We Read To Kids

A great analogy from Frank Cottrell:

Think of it, he says, the sun pours down its energy onto the surface of the planet for millennia. The leaves soak up the energy. The trees fall and turn to coal. Coal is solid sunlight, the stored memory of millions of uninhabited summers. Then one day, in Coalbrookdale, someone opens a hole in the ground and all that stored energy comes pouring out and is consumed in furnaces, engines, motors.

When we -- teachers, parents, carers, friends -- read to our children, I believe that's what we're doing. Laying down strata of fuel, fuel studded with fossils and treasures. If we ask for anything back, we burn it off too soon.

My wife and I surely did a lot of things wrong as we raised our daughters, but I think we did at least two things right: we read to them all the time, and we talked to them like we talk to everyone else. Their ability to speak and reason and imagine grew out of those simple, respectful acts.

Teaching at a university creates an upside-down dynamic by comparison, especially in a discipline many think of as being about jobs. It is the students and parents who are more likely to focus on the utility of knowledge. Students sometimes ask, "When will we use this in industry?" With the cost of tuition and the uncertainty of the times, I understand their concern. Even so, there are times I would like to say "I don't know" or, in my weaker moments, the seemingly disrespectful "I don't care". Something more important should be happening here. We are creating fuel for a lifetime.

(The Cottrell article takes an unusual route to an interesting idea. It was worth a read.)

Posted by Eugene Wallingford | Permalink | Categories: Personal, Teaching and Learning

July 19, 2016 10:32 AM

What Is The Function Of School Today?

Painter Adolph Gottlieb was dismissive of art school in the 1950s:

I'd have done what I'm doing now twenty years ago if I hadn't had to go through that crap. What is the function of the art school today? To confuse the student. To make a living for the teacher. The painter can learn from museums -- probably it is the only way he can to learn. All artists have to solve their problems in the context of their own civilization, painting what their time permits them to paint, extending the boundaries a little further.

It isn't much of a stretch to apply this to computer programming in today's world. We can learn so much these days from programs freely available on GitHub and elsewhere on the web. A good teacher can help, but in general is there a better way to learn how to make things than to study existing works and to make our own?

Most importantly, today's programmers-to-be have to solve their problems in the context of their own civilization: today's computing, whether that's mobile or web or Minecraft. University courses have a hard time keeping up with constant change in the programming milieu. Instead, they often rely on general principles that apply across most environments but which seem lifeless in their abstraction.

I hope that, as a teacher, I add some value for the living I receive. Students with interests and questions and goals help keep me and my courses alive. At least I can set a lower bound of not confusing my students any more than necessary.


(The passage above is quoted from Conversations with Artists, Selden Rodman's delightful excursion through the art world of the 1950s, chatting with many of the great artists of the era. It's not an academic treatise, but rather more an educated friend chatting with creative friends. I would thank the person who recommended this, but I have forgotten whose tweet or article did.)

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

July 13, 2016 11:19 AM

A Student Asks About Pursuing Research Projects

Faculty in my department are seeking students to work on research projects next. I've sent a couple of messages to our student mailing list this week with project details. One of my advisees, a bright guy with a good mind and several interests, sent me a question about applying. His question got to the heart of a concern many students have, so I responded to the entire student list. I thought I'd share the exchange as an open letter to all students out there who are hesitant about pursuing an opportunity.

The student wrote something close to this:

Both professors' projects seem like great opportunities, but I don't feel even remotely qualified for either of them. I imagine many students feel like this. The projects both seem like they'd entail a really advanced set of skills -- especially needing mathematics -- but they also require students with at least two semesters left of school. Should I bother contacting them? I don't want to jump the gun and rule myself out.

Many students "self-select out" -- choose not to pursue an opportunity -- because they don't feel qualified. That's too bad. You would be surprised how often the profs would be able to find a way to include a student who are interested in their work. Sometimes, they work around a skill the student doesn't have by finding a piece of the project he or she can contribute to. More often, though, they help the student begin to learn the skill they need. We learn many things best by doing them.

Time constraints can be a real issue. One semester is not enough time to contribute much to some projects. A grant may run for a year and thus work best with a student who will be around for two or more semesters. Even so, the prof may be able to find a way to include you. They like what they do and like to work with other people who do, too.

My advice is to take a chance. Contact the professor. Stop in to talk with him or her about your interest, your skills, and your constraints. The worst case scenario is that you get to know the professor a little better while finding out that this project is not a good fit for you. Another possible outcome, though, is that you find a connection that leads to something fruitful. You may be surprised!


Postcript. One student has stopped in already this morning to thank me for the encouragement and to say that he is going to contact one of the profs. Don't let a little uncertainty stand in the way of pursuing something you like.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

June 23, 2016 2:29 PM

The Most Important Thing About the "10,000-Hour Rule"


But we see the core message as something else altogether: In pretty much any area of human endeavor, people have a tremendous capacity to improve their performance, as long as they train in the right way. If you practice something for a few hundred hours, you will almost certainly see great improvement ... but you have only scratched the surface. You can keep going and going and going, getting better and better and better. How much you improve is up to you.

... courtesy of Anders Ericsson himself, in a Salon piece adapted from his new book, Peak, (written with Robert Pool). Ericsson himself, author of the oft-cited paper at the source of the rule, which was made famous by Malcolm Gladwell.

I've seen this dynamic play out over the years for many students. They claimed not to be able any good at math or programming, but then they decided to do the work. And they kept getting better. Some ended up with graduate degrees, and most ended up with surprising success in industry.

Looked at from one perspective, the so-called 10,000 Hour Rule is daunting. "Look how far I am from being really good at this..." Many people shrink in the face of this mountain, willing to settle for limits placed on them by their supposed talents. But, as my friend Richard Gabriel often says, talent doesn't determine good you get, only how fast you get good. As I quoted from Art and Fear long ago, "talent is rarely distinguishable, over the long run, from perseverance and lots of hard work".

That's the most important lesson behind Ericsson's research. If we practice right, we will get better and, with even more of the right kind of training, we will keep getting better. Our limits usually lie much farther away than we think.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 20, 2016 3:45 PM

Louis C.K. on Teaching

Louis C.K. on stage

When I read this interview with Louis C.K. last week, the following response spoke to me as a college professor, not as a stand-up comedian:

Can you explain the difference, practically, between the stand-up you were doing at your peak and what you're doing now?

I think I'm a better comedian overall than I was back then, but back then I was better at performing. When you're that greased up onstage, you just have a higher comedy IQ. It's the ability to go on any stage in the country and be perfectly present and able to maneuver the set and have great timing. Some of it is being in physical shape. When you're under pressure or strain, you get dumb, you know? It's why I started working out in boxing gyms, because you watch a guy who's fighting, he's in a terribly arduous moment and he's making intelligent choices. So to me that's when you're 55 minutes deep into your sixth show of the week, in your fifth city of the week. You have to be able to be great right in that moment. You have to be, "You're not going to believe what I'm going to do next." The audience is tired, and you have to have more energy than anyone in the room. You have to be able to control the pace. At my show last night, I was talking to myself a little bit while my mouth was moving delivering material. I was thinking, You're going too fast. Cool it. You have plenty of time and loads ... to say.

It's funny how so many of us, doing so many different things, experience so many of the same ups and downs in our professions. With a few changes to the surface of this story, it sounds like something a college instructor might say ten years on. I've even reached a point where I can talk to myself in an analytical way during a class session or a presentation. I was never as good in 2004 as Louis was, but I feel the same evolution in how I feel about my work in the classroom.

One thing I haven't tried is boxing. (Perhaps that is one of my more intelligent choices.) I have had to make some tough decisions under grueling conditions while running marathons, but those tend to unfold at a slower pace than in the ring. "Everybody has a plan until they get punched in the face."

Like Louis, I'm always trying to get better at teaching in first gear. He is probably more natural than I am in an amped-up state, too. Both are a challenge for me.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 17, 2016 2:55 PM

Education as a Way to Create Better Adults

In this Dr. Dobbs interview, Alan Kay reveals how he became interested in education as a life's work: as a teenager, he read the issue of Life magazine that introduced Margaret Bourke-White's photos from Buchenwald. Kay says:

That probably was the turning point that changed my entire attitude toward life. It was responsible for getting me interested in education. My interest in education is unglamorous. I don't have an enormous desire to help children, but I have an enormous desire to create better adults.

This desire has caused Kay to explore how children think and learn more deeply than most people do. Our greatest desires sometimes lead us down paths we would not otherwise go.

For some reason, Kay's comments on his enduring involvement in education made me think of this passage from a profile of Ludwig Wittgenstein in the Paris Review:

We all struggle to form a self. Great teaching, Wittgenstein reminds us, involves taking this struggle and engaging in it with others; his whole life was one great such struggle. In working with poor children, he wanted to transform himself, and them.

Wittgenstein wanted to create a better adult of himself and so engaged for six years in "the struggle to form a self" with elementary school students. Let's hope that the students in his charge grew into better adults as well. As Kay says later in the same interview, "Education is a double-edged sword. You have to start where people are, but if you stay there, you're not educating."

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 10, 2016 3:09 PM

Critical Thinking Skills Don't Transfer; They Overlap

A few years ago, I was giving a short presentation about one of our new programs to people from the community and campus. One of the prompts for the talk was how this program would contribute to teaching "critical thinking skills" across the curriculum. I made a mild joke about the idea, wondering aloud which programs on campus taught uncritical thinking skills. Only later did I learn that our new provost, who was in the audience, had just announced a major focus on critical thinking. Fortunately, our new provost had a sense of humor.

I don't believe that we can teach critical thinking in any useful way outside the context of a particular discipline. I do believe, though, that we can teach it as a part of any discipline -- not just in the humanities or liberal arts, which in too many people's minds don't include the sciences. Studies show that these skills don't tend to transfer when we move to a different discipline, but I am convinced that people who learn to think deeply in one discipline are better prepared to learn another discipline than someone who is learning deeply for the first time.

In a recent essay for Inside Higher Ed, John Schlueter offers a new analogy for thinking about critical thinking:

When it comes to thinking skills, it would be much more productive if we stop thinking "transfer" and start thinking "overlap". That is, once thinking skills become more explicitly taught, especially in general education classes, both professors and students will notice how thinking in the context of one domain (say, economics) overlaps with the kind of thinking processes at work in another (biology).

The idea of overlap fits nicely with how I think about these skills. Making thinking skills more explicit in our instruction might enable students to notice intersections and differences across the disciplines they study. That awareness may help them to internalize general strategies that are useful across disciplines, for times when they are in unknown waters, and be aware of possible points of failure in their own thinking.

I'm not sure if this analogy is any easier to operationalize or test than the notion of transfer, but it does give me a different way to think about thinking.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 09, 2016 4:05 PM

If You Can't Teach It, You May Not Understand It. Or Else...

In an interesting article about words and concepts, Elisa Gabbert repeats a familiar sentiment about teaching:

... the physicist Richard Feynman reportedly said, after being asked to prepare a freshman lecture on why spin-1/2 particles obey Fermi-Dirac statistics, "I couldn't reduce it to the freshman level. That means we really don't understand it."

When I read this, my inner Sheldon Cooper thought, "With the data at hand, you really can't draw that conclusion. All you can say with absolute certainty is that you don't understand it."

Actually, I empathize deeply Feynman's sentiment, which has been attributed to many famous people and stated in one form or other by many people who have tried to teach a challenging topic to others. Most teachers have had the experience of trying to explain an idea they think they know cold, only to find themselves stumbling over concepts or relationships that seem so obvious in their expert mind. I experience this feeling almost every semester. When I was a young teacher, such experiences disconcerted me. I soon learned that they were opportunities to understand the world better.

But I think that, at a logical level, people sometimes draw an invalid conclusion from statements of the sort Feynman reportedly made. It's certainly true that if we don't really understand a complex subject, then we probably won't be able to reduce it to a level appropriate for first-year students. But even if you do understand it really well, you still may have difficulty explaining it to beginners.

Teaching involves two parties: the teacher and the learner. Effective teaching requires being able to communicate new ideas in a way that connect with what the learner knows and can do.

To be effective teachers, we need two kinds of knowledge:

  • an understanding of the content to be communicated
  • an understanding of how to reach our intended audience

This latter understanding comes at two levels. First, we might know a specific individual well and be able to connect to his or her own personal experiences and knowledge. Second, we might understand a group, such as freshman CS students, based on some common background and maturity level.

Teaching individuals one-on-one can be most effective, but it takes a lot of time and doesn't scale well. As a result, we often find ourselves teaching a group of people all at once or writing for a mass audience. Teaching a class means being able to communicate new ideas to a group of students in a way that prepares most or all of them to learn on their own after they leave the classroom and begin to do their individual work.

Most people who try to teach find out that this is a lot harder than it looks. Over time, we begin to learn what a generic freshman CS student knows and is like. We build up a cache of stories for reaching them in different ways. We encounter pedagogical patterns of effective learning and learn ways to implement them in our teaching. We also begin to learn techniques for working with students individually so that, in our office after class, we can drop down from generic teaching to more intimate, one-on-one instruction.

If you want to find out simultaneously how well your students are understanding what you are teaching and how well you understand what you are teaching, let them ask questions. I am often amazed at the questions students ask, and equally amazed at how hard they can be to answer well. On truly glorious days, I surprise myself (and them!) with an answer or story or example that meets their needs perfectly.

However well I understand a topic, it always takes me time to figure out how to communicate effectively with a new audience. Once I understood that this was natural, it allowed me to take some of the pressure to be perfect off myself and get down to the business of learning how to teach and, often, learning computer science at a deeper level.

So, if we can't reduce some topic to the freshman level, it may well mean that we don't really understand it. But it may also mean that you don't yet understand your audience well enough. Figuring out which is true in a given case is yet another challenge that every teacher faces.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

May 18, 2016 11:27 AM

Confusion is the Sweat of Learning

That's a great line from Rhett Allain in Telling You the Answer Isn't the Answer:

Students are under the impression that when they are stuck and confused, they are doing something wrong. Think of it this way. What if you went to the gym to work out but you didn't get sweaty and you weren't sore or tired? You would probably feel like you really didn't get any exercise. The same is true for learning. Confusion is the sweat of learning.

As I read the article, I was a little concerned that Allain's story comes from a physics course designed for elementary education majors... Shouldn't education majors already know that learning is hard and that the teacher's job isn't simply to give answers? But then I realized how glad I am that these students have a chance to learn this lesson from a teacher who is patient enough to work through both the science and the pedagogy with them.

One of the biggest challenges for a teacher is designing workouts that ride along a thin line: confusing students just enough to stretch them into learning something valuable, without working them so hard that they become disheartened by the confusion and failure. This is hard enough to do when working with students individually. The larger and more diverse a class is, the more the teacher has to start shooting for the median, designing materials that work well enough often enough for most of the students and then doing triage with students on both ends of the curve.

Another is helping students learn to appreciate the confusion, perhaps even relish it. The payoff is worth the work.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

May 06, 2016 2:25 PM

Important Sentences about Learning Styles

From Learning styles: what does the research say?:

... it seems to me that the important "takeaway" from the research on learning styles is that teachers need to know about learning styles if only to avoid the trap of teaching in the style they believe works best for them. As long as teachers are varying their teaching style, then it is likely that all students will get some experience of being in their comfort zone and some experience of being pushed beyond it. Ultimately, we have to remember that teaching is interesting because our students are so different, but only possible because they are so similar. Of course each of our students is a unique individual, but it is extraordinary how effective well-planned group instruction can be.

Variety is an essential element of great teaching, and one I struggle to design into my courses. Students need both mental comfort and mental challenge. Changing pace every so often allows students to focus in earnest for a while and then consolidate knowledge in slower moments. Finally, changing format occasionally is one way to keep things interesting, and when students are interested, they are more willing to work. And that's where most learning comes from: practice and reflection.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

May 03, 2016 4:19 PM

Pair Programming is a Skill to be Learned

David Andersen offers a rather thorough list of ways that academics might adapt Google's coding practices to their research. It's a good read; check it out! I did want to comment on one small comment, because it relates to a common belief about pair programming:

But, of course, effective pair programming requires a lot of soft skills and compatible pairs. I'm not going to pretend that this solution works everywhere.

I don't pretend that pair programming works everywhere, either, or that everyone should adopt it, but I often wonder about statements like this one. Andersen seems to think that pair programming is a good thing and has helped him and members of his team's to produce high-quality code in the past. Why downplay the practice in a way he doesn't downplay other practices he recommends?

Throughout, the article encourages the use of new tools and techniques. These tools will alter the practice of his students. Some are complex enough that they will need to be taught, and practiced over some length of time, before they become an effective part of the team's workflow. To me, pair programming is another tool to be learned and practiced. It's certainly no harder than learning git...

Pair programming is a big cultural change for many programmers, and so it does require some coaching and extended practice. This isn't much different than the sort of "onboarding" that Andersen acknowledges will be necessary if he is to adopt some of Google's practices successfully in his lab upon upon his return. Pair programming takes practice and time, too, like most new skills.

I have seen the benefit of pair programming in an academic setting myself. Back when I used to teach our introductory course to freshmen, I had students pair every week in the closed lab sessions. We had thirty students in each section, but only fifteen computers in our lab. I paired students in a rotating fashion, so that over the course of fifteen weeks each student programmed with fifteen different classmates. We didn't use a full-on "pure" XP-style of pairing, but what we did was consistent with the way XP encourages pair programming.

This was a good first step for students. They got to know each other well and learned from one another. The better students often helped their partners in the way senior developers can help junior developers progress. In almost all cases, students helped each other find and fix errors. Even though later courses in the curriculum did not follow up with more pair programming, I saw benefits in later courses, in the way students interacted in the lab and in class.

I taught intro again a couple of falls ago after a long time away. Our lab has twenty-eight machines now, so I was not forced to use pair programming in my labs. I got lazy and let them work solo, with cross-talk. In the end, I regretted it. The students relied on me a lot more to help them find errors in their code, and they tended to work in the same insulated cliques throughout the semester. I don't think the group progressed as much as programmers, either, even though some individuals turned out fine.

A first-year intro lab is a very different setting than a research lab full of doctoral students. However, if freshmen can learn to pair program, I think grad students can, too.

Pair programming is more of a social change than a technical change, and that creates different issues than, say, automated testing and style checking. But it's not so different from the kind of change that capricious adherence to style guidelines or other kinds of code review impose on our individuality.

Are we computer scientists so maladjusted socially that we can't -- or can't be bothered -- to learn the new behaviors we need to program successfully in pairs? In my experience, no.

Like Andersen, I'm not advocating that anyone require pair programming in a lab. But: If you think that the benefits of pair programming exceed the cost, then I encourage you to consider having your research students or even your undergrads use it. Don't shy away because someone else thinks it can't work. Why deprive your students of the benefits?

The bottom line is this. Pair programming is a skill to be learned, like many others we teach our students.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

April 30, 2016 11:02 AM

Thinking About Untapped Extra Credit Opportunities

I don't usually offer extra credit assignments in my courses, but I did this semester. Students submitted their last scheduled homework early in the last week of classes: an interpreter for a small arithmetic language with local variables. There wasn't enough time left to assign another homework, but I had plenty of ideas for the next version of our interpreter. Students had just learned how to implement both functions and mutable data, so they could add functions, true variables, and sequences of expressions to the language. They could extend their REPL to support top-level definitions and state. They could add primitive data objects to the language, or boolean values and operators. If they added, booleans, they could add an if expression. If they were willing to learn some new Racket, they could load programs from a text file and evaluate them. I had plenty of ideas for them to try!

So I asked, "If I write up an optional assignment, how many of you would take a stab at some extra credit?" Approximately twenty of the twenty-five students present raised their hands.

I just downloaded the submission folder. The actual number of attempts was a complement of the number of hands raised: five. And, with only one exception, the students who tried the extra credit problems are the students who need it least. They are likely to get an A or a high B in the course anyway. The students who most need extra credit (and the extra practice) didn't attempt the extra credit.

SMH, as the kids say these days. But the more I thought about it, the more this made sense.

  • College students are the most optimistic people I have ever met. Many students probably raised their hand with every intention of submitting extra credit solutions. Then the reality of the last week of classes hit, and they ran out of time.

  • The students who submitted new code are likely the ones doing well enough in their other courses to be able to spare extra time for this course. They are also probably used to doing well in all of their courses, and a little uncertainty about their grade in this course may have spurred them into action. So, they may have had both more time and more internal motivation to do extra work.

  • To be fair, I don't know that the other students didn't attempt to solve some of the problems. Maybe some tried but did not submit their work. They may not have been satisfied with the quality of their code and didn't have time to seek help from me before the deadline.

  • And, if we are being honest, there is at least one more possibility. A few of the students who find themselves needing extra credit at the end of of the semester got themselves into that position by not being very disciplined in their work habits. Those students may be as optimistic as any other students, but they aren't likely to conjure up better work habits on short notice.

These reflections have me thinking... If I want to help the students who most need the help, I need to find ways to reach them sooner. I did try one thing earlier this semester that worked well for many students: the opportunity to rewrite one of their exams at home with access to all the course materials. A couple of students wrote surprisingly candid and insightful assessments of why they had performed below par under test conditions and supplied better work on their second attempt. I hope that experience helps them as they prepare for the final exam.

I've been teaching a long time. I still have much to learn.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

April 29, 2016 3:30 PM

A Personal Pantheon of Programming Books

Michael Fogus, in the latest issue of Read-Eval-Print-λove, writes:

The book in question was Thinking Forth by Leo Brodie (Brodie 1987) and upon reading it I immediately put it into my own "personal pantheon" of influential programming books (along with SICP, AMOP, Object-Oriented Software Construction, Smalltalk Best Practice Patterns, and Programmers Guide to the 1802).

Mr. Fogus has good taste. Programmers Guide to the 1802 is new to me. I guess I need to read it.

The other five books, though, are in my own pantheon influential programming books. Some readers may be unfamiliar with these books or the acronyms, or aware that so many of them are available free online. Here are a few links and details:

  • Thinking Forth teaches us how to program in Forth, a concatenative language in which programs run against a global stack. As Fogus writes, though, Brodie teaches us so much more. He teaches a way to think about programs.

  • SICP is Structure and Interpretation of Computer Programs, hailed by many as the greatest book on computer programming ever written. I am sympathetic to this claim.

  • AMOP is The Art of the Metaobject Protocol, a gem of a book that far too few programmers know about. It presents a very different and more general kind of OOP than most people learn, the kind possible in a language like Common Lisp. I don't know of an authorized online version of this book, but there is an HTML copy available.

  • Object-Oriented Software Construction is Bertrand Meyer's opus on OOP. It did not affect me as deeply as the other books on this list, but it presents the most complete, internally consistent software engineering philosophy of OOP that I know of. Again, there seems to be an unauthorized version online.

  • I love Smalltalk Best Practice Patterns and have mentioned it a couple of times over the years [ 1 | 2 ]. Ounce for ounce, it contains more practical wisdom for programming in the trenches than any book I've read. Don't let "Smalltalk" in the title fool you; this book will help you become a better programmer in almost any language and any style. I have a PDF of a pre-production draft of SBPP, and Stephane Ducasse has posted a free online copy, with Kent's blessing.

Paradigms of Artificial Intelligence Programming

There is one book on my own list that Fogus did not mention: Paradigms of Artificial Intelligence Programming, by Peter Norvig. It holds perhaps the top position in my personal pantheon. Subtitled "Case Studies in Common Lisp", this book teaches Common Lisp, AI programming, software engineering, and a host of other topics in a classical case studies fashion. When you finish working through this book, you are not only a better programmer; you also have working versions of a dozen classic AI programs and a couple of language interpreters.

Reading Fogus's paragraph of λove for Thinking Forth brought to mind how I felt when I discovered PAIP as a young assistant professor. I once wrote a short blog entry praising it. May these paragraphs stand as a greater testimony of my affection.

I've learned a lot from other books over the years, both books that would fit well on this list (in particular, A Programming Language by Kenneth Iverson) and others that belong on a different list (say, Gödel, Escher, Bach -- an almost incomparable book). But I treasure certain programming books in a very personal way.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Software Development, Teaching and Learning

April 05, 2016 4:06 PM

Umberto Eco and the Ineffable Power of Books

In What Unread Books Can Teach Us Oliver Burkeman relates this story about novelist and scholar Umberto Eco:

While researching his own PhD, Eco recalls, he got deeply stuck, and one day happened to buy a book by an obscure 19th-century abbot, mainly because he liked the binding. Idly paging through it, he found, in a throwaway line, a stunning idea that led him to a breakthrough. Who'd have predicted it? Except that, years later, when a friend asked to see the passage in question, he climbed a ladder to a high bookshelf, located the book... and the line wasn't there. Stimulated by the abbot's words, it seems, he'd come up with it himself. You never know where good ideas will come from, even when they come from you.

A person can learn something from a book he or or she has read, even if the book doesn't contain what the person learned. This is a much steadier path to knowledge than resting in the comfort that all information is available at the touch of a search engine.

A person's anti-library helps to make manifest what one does not yet know. As Eco reminds us, humility is an essential ingredient in this prescription.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

March 31, 2016 2:00 PM

TFW Your Students Get Abstraction

A colleague sent me the following exchange from his class, with the tag line "Best comments of the day." His students were working in groups to design a Java program for Conway's Game of Life.

Student 1: I can't comprehend what you are saying.

Student 2: The board doesn't have to be rectangular, does it?

Instructor: In Conway's design, it was. But abstractly, no.

Student 3: So you could have a board of different shapes, or you could even have a three-dimensional "board". Each cell knows its neighbors even if we can't easily display it to the user.

Instructor: Sure, "neighbor" is an abstract concept that you can implement differently depending on your need.

Student 2: I knew there was a reason I took linear algebra.

Student 1: Ok. So let's only allow rectangular boards.

Maybe Student 1 still can't comprehend what everyone is saying... or perhaps he or she understands perfectly well and is a pragmatist. YAGNI for the win!

It always makes me happy when a student encounters a situation in which linear algebra is useful and recognizes its applicability unprompted.

I salute all three of these students, and the instructor who is teaching the class. A good day.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

March 30, 2016 3:21 PM

Quick Hits at the University

This morning I read three pieces with some connection to universities and learning. Each had a one passage that made me smart off silently as I pedaled.

From The Humanities: What's The Big Idea?:

Boyarin describes his own research as not merely interdisciplinary but "deeply post-disciplinary." (He jokes that when he first came to Berkeley, his dream was to be 5 percent in 20 departments.)

Good luck getting tenure that way, dude.

"Deeply post-disciplinary" is a great bit of new academic jargon. Universities are very much organized by discipline. Figuring out how to support scholars who work outside the lines is a perpetual challenge, one that we really should address at scale if we want to enable universities to evolve.

From this article on Bernie Sanders's free college plan:

Big-picture principles are important, but implementation is important, too.

Hey, maybe he just needs a programmer.

Implementing big abstractions is hard enough when the substance is technical. When you throw in social systems and politics, implementing any idea that deviates very far from standard practice becomes almost impossible. Big Ball of Mud, indeed.

From Yours, Isaac Asimov: A Life in Letters:

Being taught is the intellectual analog of being loved.

I'll remind my students of this tomorrow when I give them Exam 3, on syntactic abstraction. "I just called to say 'I love you'."

Asimov is right. When I think back on all my years in school, I feel great affection for so many of my teachers, and I recall feeling their affection for me. Knowledge is not only power, says Asimov; it is happiness. When people help me learn they offer me knew ways to be happy.

( The Foundation Trilogy makes me happy, too.)

Posted by Eugene Wallingford | Permalink | Categories: General, Personal, Teaching and Learning

March 18, 2016 9:58 AM

Thoughts for Programmers from "Stay on the Bus"

Somehow, I recently came across a link to Stay on the Bus, an excerpt from a commencement speech Arno Rafael Minkkinen gave at the New England School of Photography in June 2004. It is also titled "The Helsinki Bus Station Theory: Finding Your Own Vision in Photography". I almost always enjoy reading the thoughts of an artist on his or her own art, and this was no exception. I also usually hear echoes of what I feel about my own arts and avocations. Here are three.

What happens inside your mind can happen inside a camera.

This is one of the great things about any art. What happens inside your mind can happen in a piano, on a canvas, or in a poem. When people find the art that channels their mind best, beautiful things -- and lives -- can happen.

One of the things I like about programming is that is really a meta-art. Whatever happens in your mind can happen inside a camera, inside a piano, on a canvas, or in a poem. Yet whatever happens inside a camera, inside a piano, or on a canvas can happen inside a computer, in the form of a program. Computing is a new medium for experimenting, simulating, and creating.

Teachers who say, "Oh, it's just student work," should maybe think twice about teaching.

Amen. There is no such thing as student work. It's the work our students are ready to make at a particular moment in time. My students are thinking interesting thoughts and doing their best to make something that reflects those thoughts. Each program, each course in their study is a step along a path.

All work is student work. It's just that some of us students are at a different point along our paths.

Georges Braque has said that out of limited means, new forms emerge. I say, we find out what we will do by knowing what we will not do.

This made me think of an entry I wrote many years ago, Patterns as a Source of Freedom. Artists understand better than programmers sometimes that subordinating to a form does not limit creativity; it unleashes it. I love Minkkinen's way of saying this: we find out what we will do by knowing what we will not do. In programming as in art, it is important to ask oneself, "What will I not do?" This is how we discover we will do, what we can do, and even what we must do.

Those are a few of the ideas that stood out to me as I read Minkkinen's address. The Helsinki Bus Station Theory is a useful story, too.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development, Teaching and Learning

March 11, 2016 3:59 PM

The Irony of "I Didn't Have Time to Use Your Technique..."

All last spring, I planned to blog about my Programming Languages class but never got around to writing more than a couple of passing thoughts. I figured this spring would be different, yet here we are at the end of Week 9 and I've not even mentioned the course. This is how guys like me fail in personal relationships. We think a lot of good thoughts but don't follow through with our time and attention.

I am tempted to say that this has been a seesaw semester, but on reflection things have gone pretty well. I have a good group of students, most of whom are engaged in the topic and willing to interact in class. (Lack of interest and engagement was a bit of a problem last spring.) We've had fun in and out of class.

The reason it sometimes feels like I'm on a seesaw is that the down moments stand out more in my memory than they deserve to. You'd think that, as long as I've been teaching, I would have figured out how to manage this dynamic more effectively. Maybe it's just a part of being a teacher. We want things to go perfectly for our students, and when they don't we have to wonder why not.

One source of concern this semester has been the average exam score for the first two tests. They have been lower than historic averages in the course. Have I changed my expectations? Have I done something differently in the classroom? After taking a hard look back on my previous semesters' notes and assignments, I think not. My job now is to help this class reach the level I think they can reach. What can I do differently going forward? What can they do differently, and how do I help them do it?

I know they are capable of growth. Early last month, PhD Comics ran a strip titled The Five Most Typed Words in Academia. The winner was "Sorry for the late reply". At the time, the five most common words my students had said to me in the young semester were:

I didn't read the instructions.

For example, the student would say, "This problem was hard because I didn't know how to take the remainder properly." Me: "I gave that information in the instructions for the assignment." Student: "Oh, I didn't read the instructions."

Fortunately, we seem to moved beyond that stage of our relationship, as most students have come to see that the assignment may actually include some clues to help them out. Or maybe they've just stopped telling me that they don't read the instructions. If so, I appreciate them sparing my feelings.

A related problem is a perennial issue in this course: We learn a new technique, and some students choose not to use it. Writing code to process language expressions is a big part of the course, so we study some structural recursion patterns for processing a grammar specified in BNF. Yet a few students insist on whacking away at the problem with nothing more than a cond expression and a brave heart. When I ask them why, they sometimes say:

I didn't have time to use the technique we learned in class, so...

... so they spent twice as long trying to find their way to a working solution. Even when they find one, the code is generally unreadable even to them. Functional programming is hard, they say.

Fortunately, again, many seem to moved beyond this stage and are now listening to their data structures. The result is beautiful code: short, clear, and expressive. Grading such programs is a pleasure.

It recently occurred to me, though, that I have been guilty of the "I didn't have time to use your technique..." error myself. While trying to improve the recursive programming unit of the course over the last few years, I seem to have invented my own version of the Design Recipe from How to Design Programs. In the spirit of Greenspun's Tenth Rule, I have probably reinvented an ad hoc, informally-specified, bug-ridden, pedagogically less sound version of the Design Recipe.

As we used to say in Usenet newsgroups, "Pot. Kettle, Black." Before the next offering of the course, I intend to do my homework properly and find a way to integrate HtDP's well-tested technique into my approach.

These things stand out in my mind, yet I think that the course is going pretty well. And just when I begin to wonder whether I've been letting the class down, a few students stop in my office and say that this is one of their favorite courses CS courses ever. They are looking forward to the compiler course this fall. I'm not sure students realize the effect such words have on their instructors -- at least on this one.

Off to spring break we go. When we get back: lexical addressing and (eventually) a look at stateful programming. Fun and surprise await us all.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

March 02, 2016 4:45 PM

Why Bother With Specialty Languages?

In Sledgehammers vs Nut Crackers, Thomas Guest talks about pulling awk of the shelf to solve a fun little string-processing problem. He then shows a solution in Python, one of his preferred general-purpose programming languages. Why bother with languages like awk when you have Python at the ready? Guest writes:

At the outset of this post I admitted I don't generally bother with awk. Sometimes, though, I encounter the language and need to read and possibly adapt an existing script. So that's one reason to bother. Another reason is that it's elegant and compact. Studying its operation and motivation may help us compose and factor our own programs -- programs far more substantial than the scripts presented here, and in which there will surely be places for mini-languages of our own.

As I watch some of my students struggle this semester to master Racket, recursive programming, and functional style, I offer them hope that learning a new language and a new style will make them better Python and Java programmers, even if they never write another Racket or Lisp program again. The more different ways we know how to think about problems and solutions, the more effective we can be as solvers of problems. Of course, Racket isn't a special purpose language, and a few students find they so like the new style that they stick with the language as their preferred tool.

Experienced programmers understand what Guest is saying, but in the trenches of learning, it can be hard to appreciate the value of knowing different languages and being able to think in different ways. My sledgehammer works fine, my students say; why am I learning to use a nutcracker? I have felt that sensation myself.

I try to keep this feeling in mind as my students work hard to master a new way of thinking. This helps me empathize with their struggle, all the while knowing that Racket will shape how some of them think about every program they write in the future.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

February 14, 2016 11:28 AM

Be Patient, But Expect Better. Then Make Better.

In Reversing the Tide of Declining Expectations Matthew Butterick exhorts designers to expect more from themselves, as well as from the tools they use. When people expect more, other people sometimes tell them to be patient. There is a problem with being patient:

[P]atience is just another word for "let's make it someone else's problem. ... Expectations count too. If you have patience, and no expectations, you get nothing.

But what if you find the available tools lacking and want something better?

Scientists often face this situation. My physicist friends seem always to be rigging up some new apparatus in order to run the experiments they want to run. For scientists and so many other people these days, though, if they want a new kind of tool, they have to write a computer program.

Butterick tells a story that shows designers can do the same:

Let's talk about type-design tools. If you've been at the conference [TYPO Berlin, 2012], maybe you saw Petr van Blokland and Frederick Berlaen talking about RoboFont yesterday. But that is the endpoint of a process that started about 15 years ago when Erik and Petr van Blokland, and Just van Rossum (later joined by many others) were dissatisfied with the commercial type-design tools. So they started building their own. And now, that's a whole ecosystem of software that includes code libraries, a new font-data format called UFO, and applications. And these are not hobbyist applications. These are serious pieces of software being used by professional type designers.

What makes all of this work so remarkable is that there are no professional software engineers here. There's no corporation behind it all. It's a group of type designers who saw what they needed, so they built it. They didn't rely on patience. They didn't wait for someone else to fix their problems. They relied on their expectations. The available tools weren't good enough. So they made better.

That is fifteen years of patience. But it is also patience and expectation in action.

To my mind, this is the real goal of teaching more people how to program: programmers don't have to settle. Authors and web designers create beautiful, functional works. They shouldn't have to settle for boring or cliché type on the web, in their ebooks, or anywhere else. They can make better. Butterick illustrates this approach to design himself with Pollen, his software for writing and publishing books. Pollen is a testimonial to the power of programming for authors (as well as a public tribute to the expressiveness of a programming language).

Empowering professionals to make better tools is a first step, but it isn't enough. Until programming as a skill becomes part of the culture of a discipline, better tools will not always be used to their full potential. Butterick gives an example:

... I was speaking to a recent design-school graduate. He said, "Hey, I design fonts." And I said, "Cool. What are you doing with RoboFab and UFO and Python?" And he said, "Well, I'm not really into programming." That strikes me as a really bad attitude for a recent graduate. Because if type designers won't use the tools that are out there and available, type design can't make any progress. It's as if we've built this great spaceship, but none of the astronauts want to go to Mars. "Well, Mars is cool, but I don't want to drive a spaceship. I like the helmet, though." Don't be that guy. Go the hell to Mars.

Don't be that person. Go to Mars. While you are at it, help the people you know to see how much fun programming can be and, more importantly, how it can help them make things better. They can expect more.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

January 24, 2016 10:33 AM

Learn Humility By Teaching

In The Books in My Life, Henry Miller writes about discussing books with an inquisitive friend:

I remember this short period vividly because it was an exercise in humility and self-control on my part. The desire to be absolutely truthful with my friend caused me to realize how very little I knew, how very little I could reveal, though he always maintained that I was a guide and mentor to him. In the brief, the result of those communions was that I began to doubt all that I had blithely taken for granted. The more I endeavored to explain my point of view, the more I floundered. He may have thought I acquitted myself well, but not I. Often, on parting from him, I would continue the inner debate interminably.

I am guessing that most anyone who teaches knows the feeling Miller describes. I feel it all the time.

I'm feeling it again this semester while teaching my Programming Languages and Paradigms course. We're learning Racket as a way to learn to talk about programming languages, and also as a vehicle for learning functional programming. One of my goals this semester is to be more honest. Whenever I find a claim in my lecture notes that sounds like dogma that I'm asking students to accept on faith, I'm trying to explain in a way that connects to their experience. Whenever students ask a question about why we do something in a particular way, I'm trying to help them really to see how the new way is an improvement over what they are used to. If I can't, I admit that it's convention and resolve not to be dogmatic about it with them.

This is a challenge for me. I am prone to dogma, and having programmed functionally in Scheme for a long time, so much of what my students experience learning Racket is deeply compiled in my brain. Why do we do that? I've forgotten, if I ever knew. I may have a vague memory that, when I don't do it that way, chaos ensues. Trust me! Unfortunately, that is not a convincing way to teach. Trying to give better answers and more constructive explanations gives rise to the sort of floundering that Miller talks about. After class, the inner debate continues as I try to figure out what I know and why, so that I can do better.

Some natural teachers may find this easy, but for me, learning to answer questions in a way that really helps students has been a decades-long lesson in humility.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

December 08, 2015 3:55 PM

A Programming Digression: Generating Excellent Numbers


Whenever I teach my compiler course, it seems as if I run across a fun problem or two to implement in our source language. I'm not sure if that's because I'm looking or because I'm just lucky to read interesting blogs and Twitter feeds.

Farey sequences as Ford circles

For example, during a previous offering, I read on John Cook's blog about Farey's algorithm for approximating real numbers with rational numbers. This was a perfect fit for the sort of small language that my students were writing a compiler for, so I took a stab at implementing it. Because our source language, Klein, was akin to an integer assembly language, I had to unravel the algorithm's loops and assignment statements into function calls and if statements. The result was a program that computed an interesting result and that tested my students' compilers in a meaningful way. The fact that I had great fun writing it was a bonus.

This Semester's Problem

Early this semester, I came across the concept of excellent numbers. A number m is "excellent" if, when you split the sequence of its digits into two halves, a and b, b² - a² equals n. 48 is the only two-digit excellent number (8² - 4² = 48), and 3468 is the only four-digit excellent number (68² - 34² = 3468). Working with excellent numbers requires only integers and arithmetic operations, which makes them a perfect domain for our programming language.

My first encounter with excellent numbers was Brian Foy's Computing Excellent Numbers, which discusses ways to generate numbers of this form efficiently in Perl. Foy uses some analysis by Mark Jason Dominus, written up in An Ounce of Theory Is Worth a Pound of Search, that drastically reduces the search space for candidate a's and b's. A commenter on the Programming Praxis article uses the same trick to write a short Python program to solve that challenge. Here is an adaptation of that program which prints all of the 10-digit excellent numbers:

    for a in range(10000, 100000):
        b = ((4*a**2+400000*a+1)**0.5+1) / 2.0
        if b == int(b):
           print( int(str(a)+str(int(b))) )

I can't rely on strings or real numbers to implement this in Klein, but I could see some alternatives... Challenge accepted!

My Standard Technique

We do not yet have a working Klein compiler in class yet, so I prefer not to write complex programs directly in the language. It's too hard to get subtle semantic issues correct without being able to execute the code. What I usually do is this:

  • Write a solution in Python.
  • Debug it until it is correct.
  • Slowly refactor the program until it uses only a Klein-like subset of Python.

This produces what I hope is a semantically correct program, using only primitives available in Klein.

Finally, I translate the Python program into Klein and run it through my students' Klein front-ends. This parses the code to ensure that it is syntactically correct and type-checks the code to ensure that it satisfies Klein's type system. (Manifest types is the one feature Klein has that Python does not.)

As mentioned above, Klein is something like integer assembly language, so converting to a Klein-like subset of Python means giving up a lot of features. For example, I have to linearize each loop into a sequence of one or more function calls, recursing at some point back to the function that kicks off the loop. You can see this at play in my Farey's algorithm code from before.

I also have to eliminate all data types other than booleans and integers. For the program to generate excellent numbers, the most glaring hole is a lack of real numbers. The algorithm shown above depends on taking a square root, getting a real-valued result, and then coercing a real to an integer. What can I do instead?

the iterative step in Newton's method

Not to worry. sqrt is not a primitive operator in Klein, but we have a library function. My students and I implement useful utility functions whenever we encounter the need and add them to a file of definitions that we share. We then copy these utilities into our programs as needed.

sqrt was one of the first complex utilities we implemented, years ago. It uses Newton's method to find the roots of an integer. For perfect squares, it returns the argument's true square root. For all other integers, it returns the largest integer less than or equal to the true root.

With this answer in hand, we can change the Python code that checks whether a purported square root b is an integer using type coercion:

    b == int(b)
into Klein code that checks whether the square of a square root equals the original number:
    isSquareRoot(r : integer, n : integer) : boolean
      n = r*r

(Klein is a pure functional language, so the return statement is implicit in the body of every function. Also, without assignment statements, Klein can use = as a boolean operator.)

Generating Excellent Numbers in Klein

I now have all the Klein tools I need to generate excellent numbers of any given length. Next, I needed to generalize the formula at the heart of the Python program to work for lengths other than 10.

For any given desired length, let n = length/2. We can write any excellent number m in two ways:

  • a10n + b (which defines it as the concatenation of its front and back halves)
  • b² - a² (which defines it as excellent)

If we set the two m's equal to one another and solve for b, we get:

    b = -(1 + sqrt[4a2 + 4(10n)a + 1])

Now, as in the algorithm above, we loop through all values for a with n digits and find the corresponding value for b. If b is an integer, we check to see if m = ab is excellent.

The Python loop shown above works plenty fast, but Klein doesn't have loops. So I refactored the program into one that uses recursion. This program is slower, but it works fine for numbers up to length 6:

    > python3.4 generateExcellent.py 6

Unfortunately, this version blows out the Python call stack for length 8. I set the recursion limit to 50,000, which helps for a while...

    > python3.4 generateExcellent.py 8
    Segmentation fault: 11


Next Step: See Spot Run

The port to an equivalent Klein program was straightforward. My first version had a few small bugs, which my students' parsers and type checkers helped me iron out. Now I await their full compilers, due at the end of the week, to see it run. I wonder how far we will be able to go in the Klein run-time system, which sits on top of a simple virtual machine.

If nothing else, this program will repay any effort my students make to implement the proper handling of tail calls! That will be worth a little extra-credit...

This programming digression has taken me several hours spread out over the last few weeks. It's been great fun! The purpose of Klein is to help my students learn to write a compiler. But the programmer in me has fun working at this level, trying to find ways to implement challenging algorithms and then refactoring them to run deeper or faster. I'll let you know the results soon.

I'm either a programmer or crazy. Probably both.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

November 20, 2015 6:02 PM

The Scientific Value of Reading Old Texts

In Numbers, Toys and Music, the editors of Plus Magazine interview Manjul Bhargava, who won a 2014 Fields Medal for his work on a problem involving a certain class of square numbers.

Bhargava talked about getting his start on problems of this sort not by studying Gauss's work from nineteenth century, but by reading the work of the seventh century mathematician Brahmagupta in the original Sanskrit. He said it was exciting to read original texts and old translations of original texts from at least two perspectives. Historically, you see an idea as it is encountered and discovered. It's an adventure story. Mathematically, you see the idea as it was when it was discovered, before it has been reinterpreted over many years by more modern mathematicians, using newer, fancier, and often more complicated jargon than was available to the original solver of the problem.

He thinks this is an important step in making a problem your own:

So by going back to the original you can bypass the way of thinking that history has somehow decided to take, and by forgetting about that you can then take your own path. Sometimes you get too influenced by the way people have thought about something for 200 years, that if you learn it that way that's the only way you know how to think. If you go back to the beginning, forget all that new stuff that happened, go back to the beginning. Think about it in a totally new way and develop your own path.

Bhargava isn't saying that we can ignore the history of math since ancient times. In his Fields-winning work, he drew heavily on ideas about hyperelliptic curves that were developed over the last century, as well as computational techniques unavailable to his forebears. He was prepared with experience and deep knowledge. But by going back to Brahmagupta's work, he learned to think about the problem in simpler terms, unconstrained by the accumulated expectations of modern mathematics. Starting from a simpler set of ideas, he was able to make the problem his own and find his own way toward a solution.

This is good advice in computing as well. When CS researchers tell us to read the work of McCarthy, Newell and Simon, Sutherland, and Engelbart, they are channeling the same wisdom that helped Manjul Bhargava discover new truths about the structure of square numbers.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

October 30, 2015 4:35 PM

Taking Courses Broad and Wide

Nearly nine years ago, digital strategist Russell Davies visited the University of Oregon to work with students and faculty in the advertising program and wrote a blog entry about his stint there. Among his reflections on what the students should be doing and learning, he wrote:

We're heading for a multi-disciplinary world and that butts right up against a university business model. If I were preparing myself for my job right now I'd do classes in film editing, poetry, statistics, anthropology, business administration, copyright law, psychology, drama, the history of art, design, coffee appreciation, and a thousand other things. Colleges don't want you doing that, that destroys all their efficiencies, but it's what they're going to have to work out.

I give similar advice to prospective students of computer science: If they intend to take their CS degrees out into the world and make things for people, they will want to know a little bit about many different things. To maximize the possibilities of their careers, they need a strong foundation in CS and an understanding of all the things that shape how software and software-enhanced gadgets are imagined, made, marketed, sold, and used.

Just this morning, a parent of a visiting high school student said, after hearing about all the computer science that students learn in our programs, "So, our son should probably drop his plans to minor in Spanish?" They got a lot more than a "no" out of me. I talked about the opportunities to engage with the growing population of Spanish-speaking Americans, even here in Iowa; the opportunities available to work for companies with international divisions; and how learning a foreign language can help students study and learn programming languages differently. I was even able to throw in a bit about grammars and the role they play in my compiler course this semester.

I think the student will continue with his dream to study Spanish.

I don't think that the omnivorous course of study that Davies outlines is at odds with the "efficiencies" of a university at all. It fits pretty well with a liberal arts education, which even of our B.S. students have time for. But it does call for some thinking ahead, planning to take courses from across campus that aren't already on some department's list of requirements. A good advisor can help with that.

I'm guessing that computer science students and "creatives" are not the only ones who will benefit from seeking a multi-disciplinary education these days. Davies is right. All university graduates will live in a multi-disciplinary world. It's okay for them (and their parents) to be thinking about careers when they are in school. But they should prepare for a world in which general knowledge and competencies buoy up their disciplinary knowledge and help them adapt over time.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

September 11, 2015 3:55 PM

Search, Abstractions, and Big Epistemological Questions

Andy Soltis is an American grandmaster who writes a monthly column for Chess Life called "Chess to Enjoy". He has also written several good books, both recreational and educational. In his August 2015 column, Soltis talks about a couple of odd ways in which computers interact with humans in the chess world, ways that raise bigger questions about teaching and the nature of knowledge.

As most people know, computer programs -- even commodity programs one can buy at the store -- now play chess better than the best human players. Less than twenty years ago, Deep Blue first defeated world champion Garry Kasparov in a single game. A year later, Deep Blue defeated Kasparov in a closely contested six-game match. By 2005, computers were crushing Top Ten players with regularity. These days, world champion Magnus Larson is no match for his chess computer.

a position in which humans see the win, but computers don't

Yet there are still moments where humans shine through. Soltis opens with a story in which two GMs were playing a game the computers thought Black was winning, when suddenly Black resigned. Surprised journalists asked the winner, GM Vassily Ivanchuk, what had happened. It was easy, he said: it only looked like Black was winning. Well beyond the computers' search limits, it was White that had a textbook win.

How could the human players see this? Were they searching deeper than the computers? No. They understood the position at a higher level, using abstractions such as "being in the square" and passed pawns like splitting a King like "pants". (We chessplayers are an odd lot.)

When you can define 'flexibility' in 12 bits,
it will go into the program.

Attempts to program computers to play chess using such abstract ideas did not work all that well. Concepts like king safety and piece activity proved difficult to implement in code, but eventually found their way into the programs. More abstract concepts like "flexibility", "initiative", and "harmony" have proven all but impossible to implement. Chess programs got better -- quickly -- when two things happened: (1) programmers began to focus on search, implementing metrics that could be applied rapidly to millions of positions, and (2) computer chips got much, much faster.

Pawn Structure Chess, by Andy Soltis

The result is that chess programs can beat us by seeing farther down the tree of possibilities than we do. They make moves that surprise us, puzzle us, and even offend our sense of beauty: "Fischer or Tal would have played this move; it is much more elegant." But they win, easily -- except when they don't. Then we explain why, using ideas that express an understanding of the game that even the best chessplaying computers don't seem to have.

This points out one of the odd ways computers relate to us in the world of chess. Chess computers crush us all, including grandmasters, using moves we wouldn't make and many of us do not understand. But good chessplayers do understand why moves are good or bad, once they figure it out. As Soltis says:

And we can put the explanation in words. This is why chess teaching is changing in the computer age. A good coach has to be a good translator. His students can get their machine to tell them the best move in any position, but they need words to make sense of it.

Teaching computer science at the university is affected by a similar phenomenon. My students can find on the web code samples to solve any problem they have, but they don't always understand them. This problem existed in the age of the book, too, but the web makes available so much material, often undifferentiated and unexplained, so, so quickly.

The inverse of computers making good moves we don't understand brings with it another oddity, one that plays to a different side of our egos. When a chess computer loses -- gasp! -- or fails to understand why a human-selected move is better than the moves it recommends, we explain it using words that make sense of human move. These are, of course, the same words and concepts that fail us most of the time when we are looking for a move to beat the infernal machine. Confirmation bias lives on.

Soltis doesn't stop here, though. He realizes that this strange split raises a deeper question:

Maybe it's one that only philosophers care about, but I'll ask it anyway:

Are concepts like "flexibility" real? Or are they just artificial constructs, created by and suitable only for feeble, carbon-based minds?

(Philosophers are not the only ones who care. I do. But then, the epistemology course I took in grad school remains one of my two favorite courses ever. The second was cognitive psychology.)


We can implement some of our ideas about chess in programs, and those ideas have helped us create machines we can no longer defeat over the board. But maybe some of our concepts are simply be fictions, "just so" stories we tell ourselves when we feel the need to understand something we really don't. I don't think so, the pragmatist in me keeps pushing for better evidence.

Back when I did research in artificial intelligence, I always chafed at the idea of neural networks. They seemed to be a fine model of how our brains worked at the lowest level, but the results they gave did not satisfy me. I couldn't ask them "why?" and receive an answer at the conceptual level at which we humans seem to live. I could not have a conversation with them in words that helped me understand their solutions, or their failures.

Now we live in a world of "deep learning", in which Google Translate can do a dandy job of translating a foreign phrase for me but never tell me why it is right, or explain the subtleties of choosing one word instead of another. Add more data, and it translates even better. But I still want the sort of explanation that Ivanchuk gave about his win or the sort of story Soltis can tell about why a computer program only drew a game because it saddled itself with inflexible pawn structure.

Perhaps we have reached the limits of my rationality. More likely, though, is that we will keep pushing forward, bringing more human concepts and abstractions within the bounds of what programs can represent, do, and say. Researchers like Douglas Hofstadter continue the search, and I'm glad. There are still plenty of important questions to ask about the nature of knowledge, and computer science is right in the middle of asking and answering them.


IMAGE 1. The critical position in Ivanchuk-Jobava, Wijk aan Zee 2015, the game to which Soltis refers in his story. Source: Chess Life, August 2015, Page 17.

IMAGE 2. The cover of Andy Soltis's classic Pawn Structure Chess. Source: the book's page at Amazon.com.

IMAGE 3. A bust of Aristotle, who confronted Plato's ideas about the nature of ideals. Source: Classical Wisdom Weekly.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

August 25, 2015 1:57 PM

The Art of Not Reading

The beginning of a new semester brings with it a crush of new things to read, write, and do, which means it's a good time to remember this advice from Arthur Schopenhauer:

Hence, in regard to our subject, the art of not reading is highly important. This consists in not taking a book into one's hand merely because it is interesting the great public at the time -- such as political or religious pamphlets, novels, poetry, and the like, which make a noise and reach perhaps several editions in their first and last years of existence. Remember rather that the man who writes for fools always finds a large public: and only read for a limited and definite time exclusively the works of great minds, those who surpass other men of all times and countries, and whom the voice of fame points to as such. These alone really educate and instruct.

"The man who writes for fools always finds a large public." You do not have to be part of it. Time is limited. Read something that matters.

The good news for me is that there is a lot of writing about compilers by great minds. This is, of course, also the bad news. Part of my job is to help my students navigate the preponderance of worthwhile readings.

Reading in my role as department head is an altogether different matter...


The passage above is from On Books and Reading, which is available via Project Gutenberg, a wonderful source of many great works.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

August 23, 2015 10:12 AM

Science Students Should Learn How to Program, and Do Research

Physicist, science blogger, and pop science author Chad Orzel offered some advice for prospective science students in a post on his Forbes blog last week. Among other things, he suggests that science students learn to program. Orzel is among many physics profs who integrate computer simulations into their introductory courses, using the Matter and Interactions curriculum (which you may recall reading about here in a post from 2007).

I like the way Orzel explains the approach to his students:

When we start doing programming, I tell students that this matters because there are only about a dozen problems in physics that you can readily solve exactly with pencil and paper, and many of them are not that interesting. And that goes double, maybe triple for engineering, where you can't get away with the simplifying spherical-cow approximations we're so fond of in physics. Any really interesting problem in any technical field is going to require some numerical simulation, and the sooner you learn to do that, the better.

This advice complements Astrachan's Law and its variants, which assert that we should not ask students to write a program if they can do the task by hand. Conversely, if they can't solve their problems by hand, then they should get comfortable writing programs that can. (Actually, that's the contrapositive of Astrachan, but "contrapositively" doesn't sound as good.) Programming is a medium for scientists, just as math is, and it becomes more important as they try to solve more challenging problems.

Orzel and Astrachan both know that the best way to learn to program is to have a problem you need a computer to solve. Curricula such as Matter and Interactions draw on this motivation and integrate computing directly into science courses. This is good news for us in computer science. Some of the students who learn how to program in their science courses find that they like it and want to learn more. We have just the courses they need to go deeper.

I concur with all five of Orzel's suggestions for prospective science students. They apply as well to computer science students as to those interested in the physical sciences. When I meet with prospective CS students and their families, I emphasize especially that students should get involved in research. Here is Orzel's take:

While you might think you love science based on your experience in classes, classwork is a pale imitation of actual science. One of my colleagues at Williams used a phrase that I love, and quote all the time, saying that "the hardest thing to teach new research students is that this is not a three-hour lab."

CS students can get involved in empirical research, but they also have the ability to write their own programs to explore their own ideas and interests. The world of open source software enables them to engage the discipline in ways that preceding generations could only have dreamed of. By doing empirical CS research with a professor or working on substantial programs that have users other than the creators, students can find out what computer science is really about -- and find out what they want to devote their lives to.

As Orzel points out, this is one of the ways in which small colleges are great for science students: undergrads can more readily become involved in research with their professors. This advantage extends to smaller public universities, too. In the past year, we have had undergrads do some challenging work on bioinformatics algorithms, motion virtual manipulatives, and system security. These students are having a qualitatively different learning experience than students who are only taking courses, and it is an experience that is open to all undergrad students in CS and the other sciences here.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

August 19, 2015 4:07 PM

Working Too Much Means Never Having to Say "No"

Among the reasons David Heinemeier Hansson gives in his advice to Fire the Workaholics is that working too much is a sign of bad judgment:

If all you do is work, your value judgements are unlikely to be sound. Making good calls on "is it worth it?" is absolutely critical to great work. Missing out on life in general to put more hours in at the office screams "misguided values".

I agree, in two ways. First, as DHH says, working too much is itself a general indicator that your judgment is out of whack. Second is the more specific case:

For workaholics, doing more work always looks like a reasonable option. As a result, when you are trying to decide, "Should I make this or not?", you never have to choose not to make the something in question -- even when not making it is the right thing to do. That sort of indifferent decision making can be death in any creative endeavor.

Posted by Eugene Wallingford | Permalink | Categories: General, Software Development, Teaching and Learning

August 04, 2015 1:00 PM

Concrete, Then Abstract

One of the things that ten years teaching the same topic has taught Daniel Lemire is that students generally learn more effectively when they learn practical skills first and only then confront the underlying theory:

Though I am probably biased, I find that it is a lot harder to take students from a theoretical understanding to a practical one... than to take someone with practical skills and teach him the theory. My instinct is that most people can more easily acquire an in-depth practical knowledge through practice (since the content is relevant) and they then can build on this knowledge to acquire the theory.

He summarizes the lesson he learned as:

A good example, well understood, is worth a hundred theorems.

My years of teaching have taught me similar lessons. I described a related idea in Examples First, Names Last: showing students examples of an idea before giving it a name.

Lemire's experience teaching XML and my experience teaching a number of topics, including the object-oriented programming example in that blog post, are specific examples of a pattern I usually call Concrete, Then Abstract. I have found this to be an effective strategy in my teaching and writing. I may have picked up the name from Ralph Johnson at ChiliPLoP 2003, where we were part of a hot topic group sketching programming patterns for beginning programmers. Ralph is a big proponent of showing concrete examples before introducing abstract ideas. You can see that in just about every pattern, paper, and book he has written.

My favorite example of "Concrete, Then Abstract" this week is in an old blog entry by Scott Vokes, Making Diagrams with Graphviz. I recently came back to an idea I've had on hold for a while: using Graphviz to generate a diagram showing all of my department's courses and prerequisites. Whenever I return to Graphviz after time away, I bypass its documentation for a while and pull up instead a cached link to Scott's short introduction. I immediately scroll down to this sample program written in Graphviz's language, DOT:

an example program in Graphviz's DOT language

... and the corresponding diagram produced by Graphviz:

an example diagram produced by Graphviz

This example makes me happy, and productive quickly. It demonstrates an assortment of the possibilities available in DOT, including several specific attributes, and shows how they are rendered by Graphviz. With this example as a starting point, I can experiment with variations of my own. If I ever want or need more, I dig deeper and review the grammar of DOT in more detail. By that time, I have a pretty good practical understanding of how the language works, which makes remembering how the grammar works easier.

Sometimes, the abstract idea to learn, or re-learn, is a context-free grammar. Sometimes, it's a rule for solving a class of problems or a design pattern. And sometimes, it's a theorem or a theory. In all these cases, examples provide hooks that help us learn an abstract idea that is initially hard for us to hold in our heads.

Posted by Eugene Wallingford | Permalink | Categories: Patterns, Teaching and Learning

July 29, 2015 2:10 PM

How Do You Know If It Is Good? You Don't.

In the Paris Review's Garrison Keillor, The Art of Humor No. 2, Keillor thinks back to his decision to become a writer, which left him feeling uncertain about himself:

Someone once asked John Berryman, How do you know if something you've written is good? And John Berryman said, You don't. You never know, and if you need to know then you don't want to be a writer.

This doesn't mean that you don't care about getting better. It means that you aren't doing it to please someone else, or at least that your doing it is not predicated on what someone else thinks. You are doing it because that's what you think about. It means that you keep writing, whether it's good or not. That's how you get better.

It's always fun to watch our students wrestle with this sort of uncertainty and come out on the other side of the darkness. Last fall, I taught first-semester freshmen who were just beginning to find out if they wanted to be programmers or computer scientists, asking questions and learning a lot about themselves. This fall, I'm teaching our senior project course, with students who are nearing the end of their time at the university. Many of them think a lot about programming and programming languages, and they will drive the course with their questions and intensity. As a teacher, I enjoy both ends of the spectrum.

Posted by Eugene Wallingford | Permalink | Categories: Software Development, Teaching and Learning

July 27, 2015 2:23 PM

The Flip Side to "Programming for All"

a thin volume of William Blake

We all hear the common refrain these days that more people should learn to program, not just CS majors. I agree. If you know how to program, you can make things. Even if you don't write many programs yourself, you are better prepared to talk to the programmers who make things for you. And even if you don't need to talk to programmers, you have expanded your mind a bit to a way of thinking that is changing the world we live in.

But there are two sides to this equation, as Chris Crawford laments in his essay, Fundamentals of Interactivity:

Why is it that our entertainment software has such primitive algorithms in it? The answer lies in the people creating them. The majority are programmers. Programmers aren't really idea people; they're technical people. Yes, they use their brains a great deal in their jobs. But they don't live in the world of ideas. Scan a programmer's bookshelf and you'll find mostly technical manuals plus a handful of science fiction novels. That's about the extent of their reading habits. Ask a programmer about Rabelais, Vivaldi, Boethius, Mendel, Voltaire, Churchill, or Van Gogh, and you'll draw a blank. Gene pools? Grimm's Law? Gresham's Law? Negentropy? Fluxions? The mind-body problem? Most programmers cannot be troubled with such trivia. So how can we expect them to have interesting ideas to put into their algorithms? The result is unsurprising: the algorithms in most entertainment products are boring, predictable, uninformed, and pedestrian. They're about as interesting in conversation as the programmers themselves.

We do have some idea people working on interactive entertainment; more of them show up in multimedia than in games. Unfortunately, most of the idea people can't program. They refuse to learn the technology well enough to express themselves in the language of the medium. I don't understand this cruel joke that Fate has played upon the industry: programmers have no ideas and idea people can't program. Arg!

My office bookshelf occasionally elicits a comment or two from first-time visitors, because even here at work I have a complete works of Shakespeare, a thin volume of William Blake (I love me some Blake!), several philosophy books, and "The Brittanica Book of Usage". I really should have some Voltaire here, too. I do cover one of Crawford's bases: a recent blog entry made a software analogy to Gresham's Law.

In general, I think you're more likely to find a computer scientist who knows some literature than you are to find a literary professional who knows much CS. That's partly an artifact of our school system and partly a result of the wider range historically of literature and the humanities. It's fun to run into a colleague from across campus who has read deeply in some area of science or math, but rare.

However, we are all prone to fall into the chasm of our own specialties and miss out on the well-roundedness that makes us better at whatever specialty we practice. That's one reason that, when high school students and their parents ask me what students should take to prepare for a CS major, I tell them: four years of all the major subjects, including English, math, science, social science, and the arts; plus whatever else interests them, because that's often where they will learn the most. All of these topics help students to become better computer scientists, and better people.

And, not surprisingly, better game developers. I agree with Crawford that more programmers should be learn enough other stuff to be idea people, too. Even if they don't make games.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Software Development, Teaching and Learning

June 29, 2015 1:58 PM

Bridging the Gap Between Learning and Doing

a sketch of bridging the gap

I recently learned about the work of Amelia McNamara via this paper published as Research Memo M-2014-002 by the Viewpoints Research Institute. McNamara is attacking an important problem: the gap between programming tools for beginners and programming tools for practitioners. In Future of Statistical Programming, she writes:

The basic idea is that there's a gap between the tools we use for teaching/learning statistics, and the tools we use for doing statistics. Worse than that, there's no trajectory to make the connection between the tools for learning statistics and the tools for doing statistics. I think that learners of statistics should also be doers of statistics. So, a tool for statistical programming should be able to step learners from learning statistics and statistical programming to truly doing data analysis.

"Learners of statistics should also be doers of statistics." -- yes, indeed. We see the same gap in computer science. People who are learning to program are programmers. They are just working at a different level of abstraction and complexity. It's always a bit awkward, and often misleading, when we give novice programmers a different set of tools than we give professionals. Then we face a new learning barrier when we ask them to move up to professional tools.

That doesn't mean that we should turn students loose unprotected in the wilds of C++, but it does require that that we have a pedagogically sound trajectory for making the connection between novice languages and tools and those used by more advanced programmers.

It also doesn't mean that we can simply choose a professional language that is in some ways suitable for beginners, such as Python, and not think any more about the gap. My recent experience reminds me that there is still a lot of complexity to help our students deal with.

McNamara's Ph.D. dissertation explored some of the ways to bridge this gap in the realm of statistics. It starts from the position that the gap should not exist and suggests ways to bridge it, via both better curricula and better tools.

Whenever I experience this gap in my teaching or see researchers trying to make it go away, I think back to Alan Kay's early vision for Smalltalk. One of the central tenets of the Smalltalk agenda was to create a language flexible and rich enough that it could accompany the beginner as he or she grew in knowledge and skill, opening up to a new level each time the learner was ready for something more powerful. Just as a kindergartener learns the same English language used by Shakespeare and Joyce, a beginning programmer might learn the same language as Knuth and Steele, one that opens up to a new level each time the learner is ready.

We in CS haven't done especially good job at this over the years. Matthias Felleisen and the How to Design Programs crew have made perhaps the most successful effort thus far. (See *SL, Not Racket for a short note on the idea.) But this project has not made a lot of headway yet in CS education. Perhaps projects such as McNamara's can help make inroads for domain-specific programmers. Alan Kay may harbor a similar hope; he served as a member of McNamara's Ph.D. committee.

Posted by Eugene Wallingford | Permalink | Categories: Computing, Teaching and Learning

June 16, 2015 3:17 PM

Dr. Seuss on Research

Reading about the unusual ideas in TempleOS reminded me of a piece of advice I received from the great philosopher of epistemology, Dr. Seuss:

If you want to get eggs
you can't buy at a store,
You have to do things
never thought of before.

As Peter T. Hooper learned in Scrambled Eggs Super, discovering or creating something new requires that we think unusual, or even outrageous, thoughts.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

June 09, 2015 2:48 PM

I'm Behind on Blogging About My Courses...

... so much so, that I may never catch up. The last year and a half have been crazy, and I simply have not set aside enough time to blog. A big part of the time crunch was teaching three heavy preps in 2014: algorithms, agile software development, and our intro course. It is fitting, then, that blogging about my courses has suffered most of all -- even though, in the moment, I often have plenty to say. Offhand, I can think of several posts for which I once had big plans and for which I still have drafts or outlines sitting in my ideas/ folder:

  • readers' thoughts on teaching algorithms in 2014, along with changes I made to my course. Short version: The old canon still covers most of the important bases.
  • reflections on teaching agile dev again after four years. Short version: The best learning still happens in the trenches working with the students, who occasionally perplex me and often amaze me.
  • reflections on teaching Python in the intro for the first course for the first time. Short version: On balance, there are many positives, but wow, there is a lot of language there, and way too many resources.
  • a lament on teaching programming languages principles when the students don't seem to connect with the material. Surprise ending: Some students enjoyed the course more than I realized.

Thoughts on teaching Python stand out as especially trenchant even many months later. The intro course is so important, because it creates habits and mindsets in students that often long outlive the course. Teaching a large, powerful, popular programming language to beginners in the era of Google, Bing, and DuckDuckGo is a Sisyphean task. No matter how we try to guide the students' introduction to language features, the Almighty Search Engine sits ever at the ready, delivering size and complexity when they really need simple answers. Maybe we need language levels a lá the HtDP folks.

Alas, my backlog is so deep that I doubt I will ever have time to cover much of it. Life goes on, and new ideas pop up every day. Perhaps I can make time the posts outlined above.

Right now, my excitement comes from the prospect of teaching my compilers course again for the first time in two years. The standard material still provides a solid foundation for students who are heading off into the the world of software development. But in the time since I last taught the course, some neat things have happened in the compiler world that will make the course better, if only by putting the old stuff into a more modern context. Consider announcements just this week about Swift, in particular that the source code is being open-sourced and the run-time ported to Linux. The moment these two things happen, the language instantly becomes of greater interest to more of my students. Its openness also makes it more suitable as content for a university course.

So, there will be plenty to blog about, even if I leave my backlog untouched. That's a good thing.

Posted by Eugene Wallingford | Permalink | Categories: General, Teaching and Learning

May 22, 2015 1:58 PM

When It Comes to Learning, Motivation and Study Habits Trump Technology

A lot of people have been talking about Kentaro Toyama's Why Technology Will Never Fix Education, which appeared in the Chronicle of Higher Education earlier this week. Here is the money paragraph:

The real obstacle in education remains student motivation. Especially in an age of informational abundance, getting access to knowledge isn't the bottleneck, mustering the will to master it is. And there, for good or ill, the main carrot of a college education is the certified degree and transcript, and the main stick is social pressure. Most students are seeking credentials that graduate schools and employers will take seriously and an environment in which they're prodded to do the work. But neither of these things is cheaply available online.

My wife just completed the second of two long-term substitute teaching assignments this year in a local elementary school, so we have been discussing the daily challenges that teachers face. The combination of student motivation and support at home account for most of the variation in how well students perform and how well any given class operates. I see a similar pattern at the university. By the time students reach me, the long-term effects of strong or weak support at home has crystallized into study habits and skills. The combination of student motivation and study skills account for most of the variation I see in whether students succeed or struggle in their university courses.

This all reminds me of a short passage from Tyler Cowen's book, Average Is Over:

The more information that's out there, the greater the returns to just being willing to sit down and apply yourself. Information isn't what's scarce; it's the willingness to do something with it.

The easy availability of information made possible by technology places a higher premium on the ability of students to sit down and work hard, and the willingness to do so. We can fool ourselves into thinking we know more than we do when we look things up quickly, but many students can just as easily access the same information.

We have found ways to use technology to make information easily available, but we haven't found a way to make motivation an abundant resource. Motivation has to come from within. So do the skills needed to use the information. We can at least help students develop study habits and skills through school and family life, though these are best learned early in life. It is hard for students to change 15-20 years of bad habits after they get to college.

The irony for young people is that, while they live in an era of increasingly available information, the onus rests more than ever on what they do. That is both good news and bad.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

May 13, 2015 12:12 PM

The Big Picture

I just turned in my grades. For the most part, this is boring paperwork. Neither students nor faculty really like grades; they are something we all have to do as a part of the system. A lot of people would like to change the system and eliminate grades, but every alternative has its own weaknesses. So we all muddle along.

But there is a bigger picture, one which Matt Reed expresses eloquently:

Tolstoy once claimed that there are really only two stories, and we keep telling each of them over and over again: a stranger comes to town, and a hero goes on a quest. In higher education, we live those two stories continuously. Every semester, a new crop of strangers come to town. And every semester, we set a new group of heroes off on their respective quests.

It's May, so we see a new group of young people set of on their own quests. In a few months, we will welcome a new group of strangers. In between are the students who are in the middle of their own "stranger comes to town" story, who will return to us in the fall a little different yet much the same.

That's the big picture.

Posted by Eugene Wallingford | Permalink | Categories: Teaching and Learning

May 09, 2015 9:28 AM

A Few Thoughts on Graduation Day

Today is graduation day for the Class of 2015 at my university. CS students head out into the world, most with a job in hand or nearly so, ready to apply their hard-earned knowledge and skills to all variety of problems. It's an exciting time for them.

This week also brought two other events that have me thinking about the world in which my students my will live and the ways in which we have prepared them. First, on Thursday, the Technology Association of Iowa organized a #TechTownHall on campus, where the discussion centered on creating and retaining a pool of educated people to participate in, and help grow, the local tech sector. I'm a little concerned that the TAI blog says that "A major topic was curriculum and preparing students to provide immediate value to technology employers upon graduation." That's not what universities do best. But then, that is often what employers want and need.

Second, over the last two mornings, I read James Fallows's classic The Case Against Credentialism, from the archives of The Atlantic. Fallows gives a detailed account of the "professionalization" of many lines of work in the US and the role that credentials, most prominently university degrees, have played in the movement. He concludes that our current approach is biased heavily toward evaluating the "inputs" to the system, such as early success in school and other demonstrations of talent while young, rather than assessing the outputs, namely, how well people actually perform after earning their credentials.

Two passages toward the end stood out for me. In one, Fallows wonders if our professionalized society creates the wrong kind of incentives for young people:

An entrepreneurial society is like a game of draw poker; you take a lot of chances, because you're rarely dealt a pat hand and you never know exactly what you have to beat. A professionalized society is more like blackjack, and getting a degree is like being dealt nineteen. You could try for more, but why?

Keep in mind that this article appeared in 1985. Entrepreneurship has taken a much bigger share of the public conversation since then, especially in the teach world. Still, most students graduating from college these days are likely thinking of ways to convert their nineteens into steady careers, not ways to risk it all on the next Amazon or Über.

Then this quote from "Steven Ballmer, a twenty-nine-year-old vice-president of Microsoft", on how the company looked for new employees:

We go to colleges not so much because we give a damn about the credential but because it's hard to find other places where you have large concentrations of smart people and somebody will arrange the interviews for you. But we also have a lot of walk-on talent. We're looking for programming talent, and the degree is in no way, shape, or form very important. We ask them to send us a program they've written that they're proud of. One of our superstars here is a guy who literally walked in off the street. We talked him out of going to college and he's been here ever since.

Who would have guessed in 1985 the visibility and impact that Ballmer would have over the next twenty years? Microsoft has since evolved from the entrepreneurial upstart to the staid behemoth, and now is trying to reposition itself as an important player in the new world of start-ups and mobile technology.

Attentive readers of this blog may recall that I fantasize occasionally about throwing off the shackles of the modern university, which grow more restrictive every year as the university takes on more of the attributes of corporate and government bureaucracy. In one of my fantasies, I organize a new kind of preparatory school for prospective software developers, one with a more modern view of learning to program but also an attention to developing the whole person. That might not satisfy corporate America's need for credentials, but it may well prepare students better for a world that needs poker players as much as it needs blackjack players. But where would the students come from?

So, on a cloudy graduation day, I think about Fallows's suggestion that more focused vocational training is what many grads need, about the real value of a liberal university education to both students and society, and about how we can best prepare CS students participate to in the world. It is a world that needs not only their technical skills but also their understanding of what tech can and cannot do. As a society, we need them to take a prominent role in civic and political discourse.

One final note on the Fallows piece. It is a bit long, dragging a bit in the middle like a college research paper, but opens and closes strongly. With a little skimming through parts of less interest, it is worth a read. Thanks to Brian Marick for the recommendation.

Posted by Eugene Wallingford | Permalink | Categories: Computing, General, Teaching and Learning

April 29, 2015 1:52 PM