October 27, 2024 8:50 AM

Not a Birthday Reflection

a maple tree with flaming red leaves, against a clear blue sky, looking down a suburban street with cars and mailboxes
The colors of autumn

Today is my birthday. I won't tell you how old I am, and I promise not to pull a Gwyneth Paltrow. Trust me; no one wants that.

I do not have a birthday essay planned, or any deep reflections on the passing of time. Birthdays have never been times of deep reflection for me. As I grow older, they have not yet started to mean anything different to me, even as I realize that they will be fewer and fewer. I mostly think of them as a time to relax, think on the good things in my life, and get on with living it.

It's just as well that I have no birthday essay planned. My friend Daniel Steinberg wrote about his birthday a few weeks ago, and I cannot improve on what he said. Daniel turned 65 this year, a milestone in a culture that emphasizes youth. Daniel, though, is still learning and teaching us what he learns with his books and presentations. He notices now that the other attendees at the conferences where he speaks are much younger than he is:

I'm the same age or older than their parents.

I'm sure they see me as old.

For the most part, it is much worse in my head than in theirs.

I know this feeling. I work with college students every day. I'm older than all their parents now, and probably not that much younger than a few grandparents. I'm sure they seem me as old, but how much of that is in my own mind?

I have a few years before I reach sixty-five, but it's close enough that I've been told I should start thinking about retirement and investment accounts and a different kind of life. But I'm of the same mind as Daniel: "Retire to do what? Travel? Do things I'm interested in? I do all that now." The life of an academic, at least one fortunate enough to have found a steady, secure position, is good: we read, write, and teach the thing we love. As long as I can do these things well enough and enjoy them, I will.

2024 has been, in some ways, an eventful year. My dad died unexpectedly this summer. A couple of months later I learned that one of my college mentors died around the same time. Those were times of reflection for me. On a more uplifting note, my wife and I got to visit our daughters in Boston this spring and spend time with our favorite people in the world. Later we took a 48-hour break mid-summer to visit Minnesota and ride the full length of the Sakatah Singing Hills State Trail and back in one day. Riding 85 miles gives you plenty of time to enjoy the beauty of the world. (That's a blog post I've been meaning to write for three months...)

This is a milestone birthday for me, too, as counted by the rest of the world. However, a few years ago, I started enumerating my birthdays in hex (base 16), a shrewd move for a computer scientist. That means I am still comfortably in my 0x30s, young enough to keep doing the things I love to do.


Posted by Eugene Wallingford | Permalink | Categories: General, Personal

October 15, 2024 3:33 PM

People Love Things That Are Not Like the Internet

Andrej Karpathy loves his calculator, and I like his post about how he loves his calculator. I was planning to quote the beginning of one paragraph as a teaser, but I could not decide where to clip the passage. Each sentence is worth seeing. I hope he does not mind that I show you the entire paragraph with encouragement to read the entire post:

Let's put this in perspective to the technology we increasingly accept as normal. The calculator requires no internet connection to set up. It won't ask for bluetooth permissions. It doesn't want to know your precise location. You won't be prompted to create an account and you don't need to log in. It does not download updates every other week. You're not going to be asked over and over to create and upgrade your subscription to the Calculator+ version that also calculates sine and cosine. It won't try to awkwardly become a platform. It doesn't need your credit card on file. It doesn't ask to track your usage to improve the product. It doesn't interrupt you randomly asking you to review it or send feedback. It does not harvest your information, for it be sold later on sketchy data markets, or for it to be leaked on the dark web on the next data breach. It does not automatically subscribe you to the monthly newsletter. It does not notify you every time the Terms of Service change. It won't break when the servers go down. The computation you perform on this device is perfectly private, secure, constrained fully to the device, and no running record of it is maintained or logged anywhere. The calculator is a fully self-contained arithmetic plugin for your brain. It works today and it would work a thousand years ago. You paid for it and now it is yours. It has no other master. It just does the thing. It is perfect.

You paid for it, and now it's yours.

My favorite pieces of software and favorite creators of software embody this ideal, at least as much of it as they can given the constraints of the modern tech world. Audio Hijack from Rogue Amoeba comes to mind and Acorn from Flying Meat come to mind.

That said, I loved calculators long before the web existed at all. Young Eugene had many hours of pleasure noodling on a calculator, playing with numbers. I first learned about rounding errors and limits by typing in a number and repeatedly hitting the square root key until the display showed a 1. I computed batting averages and winning percentages for my favorite teams and players. Eventually I was computing chess ratings by hand, until I sensed what a computer program could do for me. That would become the first program I ever wrote out of passion.

Even after learning to program, I never really lost the joy of tinkering with an old handheld calculator. It just does its thing. It is perfect.


Posted by Eugene Wallingford | Permalink | Categories: Computing, Personal, Software Development

October 10, 2024 9:14 PM

TIL Two New HTML Tags

Today I learned that HTML's <strike> tag has been replaced by two tags, <del> and <s>.

I knew that <strike> had been deprecated but had never needed to learn its replacement, or that a replacement even existed. I used it occasionally back in the days when dinosaurs roamed the web, but only rarely since. When I used it, browsers always displayed the text as expected, so I took the easy route and kept on using it.

Two things have changed since the last time I used <strike>. I taught web development for the first time last fall and decided that I wanted to write modern, compliant HTML and CSS whenever possible, both as a good example for my students and as a way to up my web game to the 2020s. The second change was more abrupt: I used <strike> today and encountered a browser that no longer supports it.

At first, I figured I'd just write a little CSS to simulate the desire behavior with a class. That's the sort of thinking that knowing CSS makes possible. But I also know that HTML includes a remarkable set of elements and that we should prefer native HTML whenever possible. So I looked <strike> up in the MDN documentation. As they say, RTFM! The documentation enlightened me.

The two replacement elements have different semantics for the act of striking through text:

  • <del> is for information that has been deleted
  • <s> is for information that is no longer correct

Now I have to think about which of these I mean when I decide to strike text in a page. But I don't mind this at all. I'm a big fan of HTML's semantic elements. What we write should express our intent, and these elements help us encode meaning and structure directly into our documents.

Even better, browsers and screen readers can use the structure of a document to present it more accurately, which means that using semantic elements makes our web pages more accessible to visually-impaired readers.

Further, using semantic elements also makes our pages more ready for futures that don't exist yet. I love the story in this blog post about how pages written with semantic markup displayed properly on the Apple Watch, even though they had been written well before the product launched. (If you'd like to jump directly to that story in the post, search for "NEW TYPES OF DEVICES".)

To bring my story to a close: I decided to use a <del> tag in the page I was writing for my students. The text in question was a bad idea, so I marked it as deleted. Whenever I open up this page in the future, the markup will include a hint as to why the text has been stricken.


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

September 29, 2024 9:23 AM

Two Quotes That Aren't About Teaching But, No, They Really Are

First from French writer André Gide, in Le Traité du Narcisse (1892):

Everything has been said before. But since nobody listens we have to keep going back and beginning all over again.

Every teacher knows how Gide feels.

Then from Bruce Springsteen, in a New Yorker interview I've lost track of:

This music has not been heard at this moment, in this place, by these faces. That's why we go out there.

Springsteen said that when asked how he could still sing "Born to Run" with so much energy after decades of performing. I think something similar to myself on many teaching days. I love the thing I am teaching and, even though it's old hat to me, it's new to my students, and I want them to love it, too.

I've always been a sucker for quotes that aren't about teaching, or programming, but could be. Making that sort of connection can motivate me on those days when I need a little pick-up.

But I also realize that making connections to other disciplines is a big part of how we teach or write programs at all. Metaphors are everywhere in both. Consider this line from Zach Tellman in a recent issue of the newsletter about his book in progress, "Explaining Software Design":

The queue is a useful metaphor because it makes us ask useful questions.

We create analogies and metaphors because they help us ask useful questions. They help us see our own objects of study, or own activities, in a new way.

I guess this is my way of saying that I'm okay with my irrational fondness for applying quotes out of context to my own world. Doing so occasionally helps me ask better questions. Even when they don't, I get to smile.


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

September 28, 2024 8:51 AM

The Thrill of a Script

I decided to scratch an itch this afternoon with a trivial bit of code.

My students use a homegrown system to submit their work in my courses. After the assignment is due, I scp the assignment's directory from the server to my machine and add it to the course repository. This directory contains one subdirectory for each student, holding their individual submissions.

I use a few scripts and a couple of manual steps to review student work, write up notes for them, and send them the reviews. Most of the scripts iterate over the subdirectories. For many tasks, it is simplest to assume one subdirectory for each student in the class.

I do all this work on two machines, one at home and one in my office. I use git to keep the repos in sync.

It's always been the case that, for any given assignment, one student might not submit anything. That's not a problem when I'm running my scripts on the same machine where I downloaded the submissions. But on the other machine, which gets the data via a git push or pull, the empty student subdirectories — poof! — disappear. git tracks files, not folders.

I'm sure there is a mechanism somewhere in git for handling this sort of thing (isn't there a mechanism for everything somewhere in git?), but in the past I've done it by hand: I glanced at the subdirectory listing and, when I saw an empty folder x, I typed touch x/_nosubmit. When there is only one empty student folder, this is quick and easy. But as the number of empty student folders goes up, it becomes tedious. Two developments over the last few semesters have driven the tedium to an uncomfortable level.

First, I've noticed that the number of students who miss the initial submission deadline rising. There are a variety of reasons that this is happening. I am happy to work with students who need to submit later, but this means more empty directories when I make my first pass reviewing submissions.

Second, I am trying to give students many more low-stakes opportunities to write code and get feedback. Instead of grading one assignment per week, I may now be evaluating submissions for three different tasks.

Put these two factors together, and I rapidly grew tired of scanning subdirectory listings and touching empty files.

Sounds like time for a new command. At first I tried to do it in a single line of bash, using xargs, but that didn't work. (My intuitions about xargs often fail me.) So I wrote a simple for loop:

    for entry in $(find "$1" -type d -empty)
    do 
        touch "$entry"/_nosubmit
    done

Stash that loop in a file, chmod +x, move it to ~/bin, and the discomfort goes away.

It occurred to me almost immediately that I should have made the name of the file to touch an optional second argument, using _nosubmit, my placeholder of choice, as a default. But you know what? YAGNI. If I ever find myself in need of more flexibility, I'll add a fifth line of code to initialize a FILENAME variable and use its value in the touch line. For now, simpler is good enough.

As I wrote on Mastodon :

Several decades on, I still get a great thrill from writing a four-line shell script to automate a common task.

Simple pleasures for a simple programmer.


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

September 21, 2024 8:41 PM

Back to the Web with... a Ph.D. Dissertation

Really. Lea Verou mentioned in this blog post that she hopes to write another blog post soon explaining...

How I used web technologies instead of LaTeX to write my PhD thesis (and print it to PDF for submission), with 11ty plus several open source plugins, many of which I wrote, an ecosystem I hope to one day free more people from the tyranny of LaTeX (which was amazing in the 70s, but its ergonomics are now showing their age).

I wrote my Ph.D. dissertation in WordPerfect (yes, I am old). The idea of writing a document as large and complex as a Ph.D. dissertation in HTML and CSS is both intimidating and intriguing, a challenge worth tackling — if only I hadn't already been facing the challenge of completing my research and, you know, writing a dissertation. For me, trying to write a simple midterm or final exam for one of my courses using only HTML and CSS usually results in me banging my head against a surprising number of walls followed by an hour or so of making tedious small changes to the stylesheet to get everything Just Right.

Verou had the advantage of deep expertise in web technologies and having done her research on the same. Even so, I am impressed and may take a peek under the hood of her website to see some of her best tricks.

This reflection is a convenient way for me to preface the fact that I am teaching web development again this fall. As I wrote in an earnest appeal for assistance last spring, this is an introductory course for non-majors, covering HTML, CSS, and a little interactivity using JavaScript. The course went reasonably well the first time around, though my coverage of JavaScript fell flat with most everyone in the class, especially the non-majors. I'm still working on ways to do better when we reach JS in a month or so.

After only a few weeks, though, I have been impressed with my students' eagerness to put their new web knowledge to use. On the first real homework assignment, I asked students to create a web page using a bunch of the HTML elements we had learned. I suggested possible pages they might create but left it open for them to create any page they wanted. As you might imagine, most students like this kind of freedom.

A couple of students wrote fan pages for their favorite musical artists (*). For me, that was shades of 1995. Another student used his assignment to create an instructional guide for the dog walker he and his significant other were hiring. He apologized for creating a page he didn't think I'd care to read, but I was very happy, and told him so.

I remember how much fun I had learning to write HTML back in the early days of the web and then writing all sorts of pages about things that I cared about. That's what knowing how to write can do for you, and knowing how to write for the web means being able to share what you write with anyone who cares to read. My students are using what they're learning to write about things they care about.

That makes me happy. And I think that Verou would be proud, too.

(*) Taylor Swift really is popular... A couple of my students were surprised and a little impressed that I like Swift, too. My daughters and I have bonded over music since they were toddlers, and they love to share their musical interests with Dad. Swift is one of many artists they've turned me on to over the years.


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

September 01, 2024 12:44 PM

Knowing Enough That You Can Wait to Decide Later

I sometimes half-jokingly tell my students that, whenever they write a new piece of code, they should have at least two alternatives in mind; that way, at least they know they aren't doing the worst possible thing. (They always laugh.) That's an old Kent Beck line, which I memorialized in a blog post many years ago.

It's part joke because it's cold comfort even to experienced programmers, and because students often don't trust themselves to generate alternatives, let alone evaluate their quality. But it's also quite serious, because it can be the first step novices take on the path to becoming a reflective practitioner.

That old story came to mind obliquely yesterday when I saw this Mastodon post by Kent, which ends with:

Next time you hear, "But we have to make this decision *now*!" ask yourself, "What skills would we need in order to *not* have to make this decision until later? How can we learn those skills?"

This seems to be an instance of a question useful to ask oneself more generally. What data, knowledge, tool, or skill would I need to be able to make this decision later?

We shouldn't fetishize postponing decisions, of course. Looking for a reason to wait to make every decision could become a recipe for not making any decisions. Further, this fetish can paralyze novices, who doubt their own abilities to evaluate choices. They can find themselves in a spiral of infinite postponement.

Fortunately, as long as we don't turn this mindset into a pathology, waiting to make a decision is rarely going to be a speed bump to writing programs. There are always plenty of decisions to make, so being able to delay some is a favorable option to have in hand.

In such a world, there is great value to be found in viewing a seemingly forced decision as an opportunity to learn.

It is almost never good to be in a position of having to make a decision right now, to have no alternatives from which to choose. We shouldn't settle for that condition without doing a little work first.

~~~~

Kent has a knack for making me think more deeply with an aphorism or a simple story. I've always admired that. This post is yet another example.


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

August 18, 2024 9:07 AM

Passages for the Academic Programmer's Life

We can sharpen our tools for other than practical reasons:

I also think that there is a place for sharpening one's tools just for its own sake. Especially as we get older, and our responsibilities increase, anything related to our work can start to feel like a burden. Sometimes even a small amount of time invested in sharpening our tools can bring a bit of joy and restore motivation.
-- Laurence Tratt

I wear my department head hat so many hours a week that sometimes an opportunity to fiddle with my tools is a welcome break. It's not always the most obviously productive use of my time -- with time so precious, shouldn't I use these moments to work on my research project or write Some Serious Code? -- but that bit of joy can sustain me through a lot of dreary time later. That might even make me more productive then. If not? That's okay, too.

~~~~~

Explanations, including documentation for software, really consist of three parts:

Content, then, conveys more than itself. The prefix is reflected in what our explanation takes for granted. The suffix is reflected in what our explanation seems to value; whatever we have today, we'll probably want more tomorrow.
-- Explaining Software Design

When people talk about critical thinking and critical reading, this is what I imagine: As a reader, even of documentation for software, it's worth thinking about what the doc takes for granted and what it says about the values of the writer.

It's also worth thinking about as a writer. This is especially on point as I prepare for the fall semester that looms around the corner. What do my explanations for students take for granted? How will they recognize and deal with what is not written down? What do my explanations say about the things I value, and that I hope they come to value through the course?

~~~~~

The beginning of a new academic year is exciting, and scary, and a lot of work. It's the work we faculty choose to do.


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

August 01, 2024 5:52 PM

Lots of our code is smarter than we are

I read one of Tim Bray's recent blog posts this morning and really liked this passage, quoted from a post of his written four years ago:

The observation that computer programmers can build executable abstractions that work but they then have trouble understanding is not new and not surprising. Lots of our code is smarter than we are.

I know this happens to me. I wonder how often something similar happens to my students as they learn techniques and abstractions?

Imagine: They assemble several small pieces of code, each of which they understand individually at least a little, into a bigger program that mostly does what they want — but they have trouble understanding the program as a whole. Further, the size and complexity of the program as a whole makes them begin to doubt their understanding of the individual pieces.

That seems a little far-fetched on its face, but it would explain behavior I see in class all the time. It's a shame when a student who seems to be doing fine begins to lose confidence as the size and complexity of their programs grow. I try to address these growing pains as best I can, but so much of their learning happens away from me, back in their rooms writing code. A few ask for help and stay on track. The ones who don't, struggle and sometimes stop having fun.

If only I can help them see that this is, many ways, the natural order for even the best programmers: We build abstractions that work but which we have trouble understanding.

People like Tim Bray struggle with this, too. You'll be all right.

~~~~~

Wow. I let the entire month of July, and the last ten days of June, pass without posting. That's the first calendar month with a (0) next to it in the blog's archives. My long absence included Knowing and Doing's 20th birthday, July 9, 2004. We should have had a party!

That means July 2024 was the first month of my twenty-first year blogging. Putting up a bagel is not an auspicious start...

I have a few short posts in mind for the coming weeks. Let's see if I can follow through. I like to write here.


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

June 19, 2024 7:53 PM

I Wrote Some Code For Fun Today

One of the downsides of being department head is that much of the daily work I have to do is less interesting to me than studying computer science or writing programs. It's important work, sure, at least most of it, but it's not why I became a computer scientist.

Today, I ended up not doing most of the administrative work I had planned for the day. On the exercise bike this morning, I read the recent Quanta article about a new way to estimate the number of distinct items in a list. My mind craved computing, so I spent some time implementing the algorithm. I still have a bug somewhere, but I'm close.

Any day I get to write code for fun I call a good day. This is important work, too, because it keeps me fresh. I can justify the time practically, because the exercise also gives me raw material for my courses and for research with my undergrads. But the real value is in keeping me alive as a computer scientist.

The good feeling from writing code today is heightened knowing that tomorrow's planned administrative work can't be postponed and is not fun, for tomorrow I must finish up writing annual salary letters. I am fortunate that writing these letters provokes as little stress as possible, because the faculty in my department are all very good and are doing good work. Even so... Salary letters? Ugh.

Thus I take extra pleasure in an absorbing programming process today.

I realized something about myself as a programmer while on a bike ride with my wife this afternoon.

Even though I prefer to write code in small steps and to write tests before (or in parallel with) the code, I have a weakness: If you give me the algorithm for a task in full upfront, and I grok it, I will occasionally implement the entire algorithm upfront, too. Then I end up debugging the program one error at a time, like a caveman.

Today, I succumbed to this tendency without even thinking about it. I am human.


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