The purpose of art is to delight us; certain men and women (no smarter than you or I) whose art can delight us have been given dispensation from going out and fetching water and carrying wood. It's no more elaborate than that. — David Mamet

Apr 24 27 2024

Development

So, Thursday I had planned to implement a nifty feature that had been on the wishlist roadmap for two years. The point is to embed some objects other than images in the text presented in the Tinderbox text pane. The task requires a class called NSTextAttachment which is poorly documented, even by Apple’s standards. Here’s how it went.

Thursday morning: OK: this should be fine! Wonder why I waited so long? Let’s get it done.

Thursday midday: That’s strange: it works OK, but as soon as I save a reload, it’s gone. Hit Stack Overflow: almost nothing of use. Hit Google: one old post suggests a really clumsy way of doing persistence. Try it: it works — until I save the file. At that point, *>poof<*.

Thursday night: This is a total disaster. Perhaps there’s a solution, but this isn’t it. Unpack “Oh shit, Git!” (which is hilarious and very good) and rewind to the start of Thursday morning. Abandon hope, also the project.

Friday morning: Wait! Think about it the other way around. Imagine that you were the Apple engineer who wrote this mess. The main task is just embedding images in text, and that works. Yet this engineer wrote the API we have, which seems cockamamie, and you wrote the persistence we have, which is completely undocumented. If I had wound up in this place, what might I have been thinking about? Use that guesswork to start over.

Friday evening: What do you know? It works! By “it”, I mean a non-functional trial balloon, but by George, I think we’ve got it!

Saturday morning: What we’ve got, in fact, is a mess. Code smells from here to the horizon: indecent exposure everywhere, downcasts, and weird hacks that have to be explained in comments. Up with this we cannot put: place all Saturday plans on hold, because this cannot wait.


Aside from the total rollback, in which I indulge perhaps once or twice a year, this is pretty much what it’s like.

Apr 24 22 2024

Dinner

I’m recovering from a close encounter with modern dentistry, and I forgot to marinate the meat for a carne asada last night. I went surfing for things to do with what I had on hand. Here’s what I ended up doing, from the bottom up:

  • large slice of toasted brioche (excess from brunch French toast)
  • two slices of lox (from the brunch I’d planned, but my poor teeth weren’t up to bagels)
  • six spears of grilled asparagus
  • two poached eggs
  • a sauce of 2T mayonnaise, juice of 1 lemon, a dollop of good mustard, a slug or two of olive oil, salt and pepper

I was leery of that sauce, which pretty obviously assumes that the site’s audience isn’t up to Hollandaise. But Hollandaise is notorious for sensing weakness, and I guess in this situations I myself wasn't up to Hollandaise, or even to making my own mayonnaise. No worries, it was all very tasty indeed.

One of the odd joys of citation is coming across a footnote that cites something you don’t remember writing. From John Hartley, How We Use Stories And Why That Matters: cultural sciences in action, New York: Bloomsbury, 2020 p. 102.

[Footnote] 15. An unusually direct statement of this tension can be found by Mark Bernstein, an editor of The Victorian Web: ‘Classical architecture is a universal architecture of precision, planning, and control. Each element has its proper place and size, and each is subordinated to the greater plan. In antiquity, classicism was the architectural language of empire; in the nineteenth century it was the language of manifest destiny and of a Republic taming the wilderness; in the twentieth century, it became the language of fascism. Ruskin expounded an (admittedly ahistorical) vision of the Gothic in opposition to the Classical, emphasizing savageness and changefulness as the touchstones of the Gothic. Changefulness refers to continuous change, as the vaulted rib has no single radius of curvature but changes continuously as it flies. Savageness refers to clean breaks, to asymmetry, to unique work expressed by different hands where structural constraints allow such variation.’

I rather suspect that “unusually direct” here serves as a tactful way of saying “foolhardy.” Still, it’s fun. Hartley found this through a 2014 blog of René Merle, which is flattering in itself. Alas, that weblog seems to be lost.

Michael Dirda.

Replace books where you found them. Don’t carry on loud or long conversations. Don’t boast to the owner or manager that the old paperback of Jack Vance’s “The Dying Earth” priced at $5 is actually its scarce Hillman first edition worth $100. Do look at the books themselves, not at a handheld device that indicates what they sell for online. Otherwise, prepare to be quietly and justly reviled by those around you.

See: Browsings.

Ross Douhat (NY Times).

The left-wing temperament is, by nature, unhappier than the moderate and conservative alternatives. The refusal of contentment is essential to radical politics; the desire to take the givens of the world and make something better out of them is always going to be linked to less relaxed gratitude, than to more of a discontented itch.
Apr 24 4 2024

Flowers

Anna Gin writing on Telegram (in Russian). Nadin Brzezinski observes that, if you didn’t know this was written yesterday, you could easily think it was a diary from 1943. I took a stab at fixing up Deepl’s translation.

Today I stopped by my favorite flower store on Kharkov’s Avenue of Heroes. I was thinking that, if the electricity goes out during the day, I will tidy up the balcony. I will wash the windows, take out the flowers, and I’ll transplant the shoots because the roots are already kilometers long.
It's spring. No matter what.
The sales girl meets me on the doorstep. She says: “Oh no, what are you thinking? Begonias on the balcony this early? There might still be frost at night.”
And we stand in the amazing-smelling shop with the garden roses, and together we watch the weather. The siren squeals. We look at each other, and silently move away from the windows to the fertilizer section, and we talk about the dracaenas waking up from their winter hibernation.
God, I love my city.
Flowers

Image: Kostiantyn Vierkieiev, Kyiv, via unsplash.

How we’re approaching theming with modern CSS, by Piccalil.li.

Based on Cube.css. More on cube here.

You have to make not just decisions about pixels, but also high-level organisation decisions which the design system helps to solve. Design system work is actually diplomacy work, a lot of the time.

Rebecca Solnit wants a joyous, inviting Left — not an angry, Puritanical one. Interview with Anand Giridharadas.

“There's a kind of absolutist idea that doesn't accept imperfect and interim victories, even though that's probably all we'll ever get because the total revolution, paradise on earth, is not in my view going to happen.”

Lessons from the experts, Ton Zylstra and Elmina Wijnia.

How To Unconference Your Birthday

Lessons from the experts, Ton Zylstra and Elmina Wijnia.

How To Unconference Your Birthday

From Madison House Chef. Tasty, and not too tricky.

The consensus is that these savory muffins are too sweet, and could use a bit more cheese.

by Patrick O'Brian

A very fine time at sea, revisiting part of what really was the great historical fiction series of the century. Wonderful characters, tons of detail, a very fine sense of place (and that place is often afloat), and a deft avoidance of perfunctory scenes.

by Stephanie Damrosch

Bourdain’s Kitchen Confidential, which transformed food writing, was modeled on Down and Out In Paris. Stephanie Danler’s wonderful novel of working the front of the house, Sweetbitter, follows the plan of The Naked and The Dead. This account of waiting tables at Per Se is clearly Two Years Before The Mast: we were not made for this job and we never completely belong to this world, but having taken the job we are going to do our level best to make it work.

by Diane Josefowicz

Zinnia Zompa is 13. She lives outside Providence with her sister Zenobia, who is a nuisance, and her parents, who are perplexing. Her father runs a factory that makes plastic beads. Dad’s accountant was Mr. Marfeo, who was recently murdered in the back seat of a yellow Mercury. “What it means to be thirteen: you scoff at your brokenhearted mother, and death just feels like a change in the weather.” Dazzling, haunting, and finely wrought, this is a short novel of wondrous shadows just slightly out of reach.

I greatly enjoyed Frederick Wiseman’s documentary, Menus-Plaisirs: Les Troisgros.

It’s not for everyone. First: it’s four hours! Second, it’s all found sound, and there’s no narrative: it’s strictly daily life in a Michelin 3-star restaurant in Roanne, France. (I was led here because I’m working on reading French, and was misled by the trailers into thinking you could get French subtitles. I’m never going to learn to hear French, not with my ears, but during the pandemic a colleague shamed me into working up a reading knowledge. I’m still pretty hopeless, but can manage a light novel and can plough through weightier things at need.). Still, there’s lots of interesting material:

  • It’s true: men don’t wear ties anymore.
  • The documentary is shot as chef Michel is gradually handing the reins to his son, César. It’s an interesting study of a transition in a significant family business.
  • We spend quite a lot of time in meetings, discussing a dish or a wine. It’s interesting how they work things out.
  • The balance in the documentary between the front and back of the house is very well done. It’s great to hear cooks discuss a dish and then hear servers describe it.
  • Michel gives a nice table side talk about kitchen visits, and how they like to have guests visit the kitchen early so the cooks can see the patrons and see who “table 2” really is. I’d sensed that it was an imposition to ask, but that if asked it should be done late, when things were less hectic.
  • Are any of the Troisgros books worthwhile?

For the past two weeks, I’ve been dividing a good deal of time to refactoring the classes that let Tinderbox parse actions. It’s been a long haul.

The Parser Class: 2001

The core of the Tinderbox action parser remains Parser, a utility class that dates to very early Tinderbox. Parser collects a bunch of functions that are useful for working with strings and character streams; for example, Parser::Trim() is a static function that trims whitespace from the front and back of a string. It’s used in more than a hundred places in Tinderbox. About half of the class is this bundle of static convenience functions, handy but not very consequential. The rest of the class deals with various chores involved in parsing a character stream. For example, there’s QuoteParser, which reads a quoted string up to the next quotation mark. This gets a little trickier than it sounds because there are questions like escaped quotes, quotes inside quotes, comments, and such.

The problem with Parser was that it was all built around a character stream — an istream — and every client knew it. That was OK in 2001, because there wasn’t a plausible alternative. Of course, actions will be written as characters! Remember, the original Tinderbox was written for System 9/Carbon; there was no other way to represent strings. It was reasonable, back then, to expect that attribute names would use ASCII. Chinese or Thai? No way.

Nowadays, you’d like the option to parse UTF-8 strings and streams. In particular, Tinderbox now recognizes \u2028 (Line Separator: ctrl-Return) as an alternative line break for use when [Return] is unwanted. Recognizing multibyte UTF-8 code points in a byte stream is an ugly mess, and that’s only going to get worse over time. It would be much cleaner, nowadays, to use a proper unicode string as the backing store.

Indecent Exposure

The problem was, dozens of classes — some of them complex — knew that Parser used an istream and felt free to manipulate that istream themselves. This is the problem of indecent exposure: Parser allowed its clients to know about Parser’s internals, and even to mess around with them. So that was the first part of the refactoring: replace the concrete istream with an abstract storage class ParserStorage. ParserStore needs to provide the same functionality as the istream, but it doesn't let anyone know what’s inside or how ParserStorage works. Then, class by class, I rewrote things to use a ParserStorage object.

Building Strings

Parser sometimes builds strings, such as lists of arguments. Those, too, had been built from characters. Now, though, ParserStorage offered ways to get unichars — full unicode characters. And you can’t just put a unichar into a character stream.

Here, again, we hide the implementation inside an abstract object, TbxStringBuilder, which does the things that we formerly did with the output streams. One by one, I replaced the old ostringstreams with TbxStringBuilder. Once again, hundreds of changes, but each isolated to one place. (The 2000-test unit test suite is fairly strong for the action language, both because actions are easy to test and because actions are so handy for testing the rest of Tinderbox: if something goes wrong with the action parser, a bunch of tests will fail right quick.

Keeping A Retreat Path Open

Of course, this was an opportunity to tidy and improve lots of code not immediately connected to the refactoring. I was not entirely sure the refactoring would work, but I would hate to lose all the other changes by simply reverting to the start. So, I took care that, if things went sour, I could return to the old implementation, now sheltered behind the new abstract classes. That was a huge help. It does mean that Tinderbox now carries along a few duplicate methods: several parsers have Token() to handle modern streams and LegacyToken() to handle character streams. The old methods do little harm, and we can jettison them once everything is happy.

Rick Perlstein traces the origins of Trump’s current nonsense to remembered moments in Hollywood movies of the 1970s and 1980s.

There was the time in the last year of his presidency, amid outbreaks of violence during Black Lives Matter protests, when he promised: "When the looting starts, the shooting starts." That was a memory he’d loosed from round about 1967, when it was a slogan of Miami’s racist police chief Walter E. Headley. His onstage panegyrics in the opening months of his 2016 presidential campaign cited the 1974 vigilante fantasy Death Wish. ("Today you can’t make that movie because it’s not politically correct," he lamented. Wrong as usual. It was remade in 2018.)
Mar 24 25 2024

Margin Notes

Jillian Hess on writing marginalia.

Margin Notes
For those less mathematically inclined, there are other ways to add to a text. I’ll leave you with this: a medieval reader added in a doomed duck’s final cry “queck” (or “quack”).

by Peter Englund

A fascinating group biography of the critical month in World War II, where the group is, basically, everyone. Englund describes details from the daily life of a fascinating range of people: a German junior officer stationed near Leningrad, an Italian junior officer adrift in the North African desert, a Liberty Ship under construction in Savannah, an Australian prisoner of war, an Auschwitz inmate, a Jewish family in Shanghai, a Malaysian sailor whose freighter has been sunk and who is adrift in the South Pacific. A few of the group are famous, but weren’t famous then: Sophie Scholl, Albert Camus. Most remain obscure. No one had a good month.

Mar 24 23 2024

Lavender

What you can make with creme violette, besides an aviation.

How the Scallion Pancake Became the Most Versatile Bread in America. By Cathy Erway.

Scallion pancake breakfast sandwiches? Yes, please!