One of the most laughable moments of the Presidential Debate was when Trump asserted that “In Springfield, they’re eating the dogs. The people that came in, they’re eating the cats. They’re eating—they’re eating the pets of the people that live there.”
Anybody with half a brain can see this is an obvious racist hoax and I’m sure you can find many who can pick it apart.
But I want to look at it from another angle, from a vegan’s perspective, in particular, one who follows Gary Francione’s theory of animal rights.
So why is this racist? Obviously it is because only a horrible person would eat a cat, right? Why is it so bad that someone eats cats? Why are cats any different than chickens or pigs or cows or any of the other multitude of animals some of us eat? An adjacent hoax was that they were eating geese; have these people not heard of eating “Christmas Goose”?
There is no moral difference between eating a cat or a cow or a human. None of them want to be eaten, all are sentient and want to avoid pain and continue living. So trying to claim some moral superiority with someone else based on which animals they choose to eat is absurd.
The only way to distinguish between these cases is with speciesism, choosing some arbitrary (and in the end, meaningless) difference and use that to justify different treatment. There is no essential difference between speciesism, racism, or sexism, or any other ism you can think of. Combining the two only makes it worse.
Maybe instead of worrying about imaginary injustices caused by immigrants, you should do something about the real injustice on your plate.
I was chatting with a good friend about the collapse of the stock market on Friday and we were trying to figure out why someone would do this. It is obvious that Trump himself is so addled by narcicism and dementia that he is not likely aware of what he is doing. But I cannot believe that those around him would blindly do something so stupid as to crash the entire economy. That every single one of them could be so deluded, stupid, or, sycophantic. Someone would have tempered what he was doing. Moved the tariff percentages a bit more toward sanity. Or perhaps set a longer timeline. Something.
But then a light went on. I asked my friend “what’s the reverse of pump and dump?” This is the most logical answer. If you know the market is going to crash it is easy to make a lot of money via short sales and timing your buys. And given that you know exactly when the market will be crashing, because you are the one causing the crash, it should be easy to make a killing (ambiguity intentional). Perhaps this strategy should be called “short and crash”. [update: had I read a bit more, I would have known this is already known as short and distort]
You might think that this is insider trading, but I’m sure the SEC, now that it has been “updated” by DOGE, will correct our misconceptions. Or, at least, remain silent.
I have done no investigation into this, and it may be that nobody in the administration thought such a crash would happen; and perhaps none of them participated in widespread short sales; and it may be that the SEC has not had key enforcement personnel removed from their positions. But it is inconceivable that an administration packed to the gills with grifters and opportunists would not have taken advantage of this situation in any way whatsoever. We will likely not know for many years.
TL;DR: I listen to podcasts. A lot of them. Perhaps too many. There is a list below of my favorites. You can look at the list rather than reading my rambling introduction, I guess.
So it was 1993, the internet was a blossoming place. The world wide web was rapidly gaining over a variety of other services. I think it was an O’Rielly newsletter which pointed out the first episode of Internet Talk Radio. One of my friends had the task of downloading the audio file, which took hours, and we sat around his computer listening to it. Being that cumbersome I don’t think I ever listened to any other subsequent shows.
At one point in my life I started noticing my habbit of turning on the TV as soon as I got home from work, and it was on until I went to bed. When I was moving in the year 2000, I decided to drop that habit and since my TV was missing its antenna all I had to do was drop cable to break that habit. I replaced that habit with turning on the radio (NPR) as soon as I got home. But that was an improvement, since audio does not hinder me from doing other things around the house.
Some radio stations were starting to stream onto the internet, so I was able to follow some shows, notably Go Vegan Radio. I think it was 2003 when I heard about Cristopher Lydon’s show The Whole Wide World. Apparently this show was was the reason RSS added the ability to include audio files, which was the birth of podcasting. Though, as is often the case with me, I failed to notice the significance for several years
Sometime around 2006, after a concert of the band “Fruit”, I went to get a CD and one of the band members saw my vegan tshirt and suggested I read Peter Singer. That triggered a memory and when I got home I looked for interviews with Gary Francione. I knew that my wife had listened to an NPR interview with him which inspired her to become vegan, and I suspect I remembered him critiquing Singer. I found the Veganfreak podcast’s interview with him, and I listened to that podcast regularily as long as it ran. I think this marks the start of me actively seeking out and regularly listening to podcasts, but with several different software packages, but after I got an Android phone I settled on AntennaPod.
So, what follows are the podcasts you must listen to (this list is going to grow over time, stay tuned):
podcast | when | notes |
---|---|---|
13 Minutes to the Moon | 2019-2021 | Excellent documentary about Apollo 11 and Apollo 13. Soundtrack by Hans Zimmer. |
Death in Ice Valley | 2018-2021 | An engrossing podcast about a mysterious death in 1970 |
Dungeons of Drakkenheim | 2019- | One of my favorite actual play D&D podcasts. I am running two campaigns based on this setting. |
GM Word of the Week | 2015-2023 | A far-ranging podcast which starts with D&D terminology and covers history, mythology, and most anything else even vaguely related. I can (and do) listen to this over and over again. |
If Books Could Kill | 2022- | You know that odious bestseller self-help book? These guys will rip it apart. |
More or Less: Behind the Stats | A refuge from misinformation, I found it during the pandemic and it help maintain my sanity amongst all the misinformation. | |
Podcast Party | 2020- | A great D&D actual play podcast, well produced, well acted. |
Satanic Panic | 2020? | I have long had a fascination with the Satanic Panic and this covers a particulary alarming case of lives being destroyed as a result. |
The Bomb | 2020- | A deep dive into two different people involved in the development of the atomic bomb. |
The Bunker | 2020- | I discovered this (and several spin-off shows) at the beginning of the pandemic, and it helped me maintain my sanity during recent events. |
The Constant: A History of Getting Things Wrong | 2017- | Fascinating tales of historical screw-ups. The patreon feed is well worth it! |
The Lazy RPG Podcast | 2017- | The best podcast about D&D |
Uncivil | 2017 | An excellent podcast about the Civil War. Sadly it came to an abrupt end, I am sure they had more stories to share. |
Unobscured (first season) | 2018 | The first season is a detailed account of the Salem Witch Trials. |
I surrender. Last weekend I was looking at the decaying remnants of my garden, and then I went and tore it all out. The deer fencing, the trellises, the decaying and collapsing boards around the raised beds, the dead weeds and such from last year’s neglect. That was probably the first time I went out there in years. But now it is gone.
I spent my younger years on a small farm. My mother had a large garden, but I never really paid attention. I always had my nose in a book, or, in my teenage years, in front of a computer keyboard. I went off to college, moved to the city, and forgot about it. When I bought a house I briefly got a garden going, inspired by Eugene Coleman’s gardening TV show (back when the Discovery channel had good shows). I got a good crop of tomatoes, but between work demands and a failing marriage, that fell by the wayside. The house was sold and I spend several years moving around the country, forgetting many things: the garden, old friends, my boat, etc.
After my daughter was born it was time to settle down and buy a house. This time I had a significant amount of land and I had grand plans. But no grand results were forthcoming.
For every action there is an equal and opposite rebuke. Though with my garden it was not a proportional response, almost everything I tried was met with stunning defeat. Defeat after defeat.
Lack of sunlight is a problem, while I own half an acre, it is populated with 46 trees, many of them quite large, such that no spot in the yard gets more than a few hours of direct sunlight. It became obvious that removing trees would only partly help, as the western side of my yard borders on woods. So increasing sunlight would have required the removal of dozens of trees, many of which I don’t own.
I probably should have stopped there, but I decided to marshall ahead.
My first near-harvest, was a small eggplant. My wife saw it while she was in the house, and decided to go and pick it. As she is headed that way, she looks back out at the garden and sees a squirrel running across the yard with that eggplant in his mouth. The tomatoes next to it got partly eaten my hornworms. And the poison ivy, which is endemic here, grew up through my sheet mulch and ended up being pulled with some weeds, leading to a nasty rash.
So larger beds, more compost, in a different location. But the deer like to sample, so I built a fence. And the squirrels and woodchucks liked the looks of those pinkish tomatoes, and would try a bite: “Ew! That’s awful, let’s try the next one…” and so on. Most tomatoes that grew within a foot or two of the ground would look tempting, but when picked had a big rotten hole in the bottom of them.
Both the tomatoes and cucumbers spend the summer in a race against the various sorts of fungus and blight consuming their lower leaves, and before the end of the season the whole plants would wither, struggling to produce a few fruits. I tried zucchini several times which generally resulted in no female flowers (and, thus, no fruit) or the leaves consumed by fungus, or both.
Years ago I got a bunch of asparagus roots and planted an 8 foot row down the middle of one of the beds, that row slowly shortened, fewer and fewer shoots coming up each year, until now it seems to be a single plant, which produced a couple of shoots last year.
I have generally been a fan of no-till gardening and started most of my beds by sheet mulching: laying down a layer of cardboard and then piling leaf mulch and compost on top of it. One time I decided I should try double digging a bed. Every single time I put the shovel in the ground there was the “clunk” of a stone. I slowly got the digging done, pulling out so many stones, that, even after adding all the compost I had, I ended up with a sunken bed instead of a raised bed. Though this is no surprise given the geology of this place: The entire state was scraped clean through every ice age. There is only a thin layer of soil on top of stone.
So I constructed my beds, filled them with compost mostly from the leaves which fall every year. Nice loose soil to plant my seedlings in. But when it came to plant in those beds the next year, I found digging holes difficult, for all the roots spread through the beds. As I dug I pulled out numerous clumps of roots. At first I thought it was the leftover roots from last years plants, but I came to realize where those roots lead, as I look up at the numerous trees surrounding my yard. I am sure the majestic maples high overhead are sending their roots far and wide in the thin soil to find nourishment, and those compost-filled raised beds are pretty tasty. The seedlings in those beds end up losing out to these neighborhood bullies, coming by and stealing their lunch money (and lunch).
Maybe I should try some more shade tolerant plants, maybe some brassicas. What I quickly discovered was that cabbage worms are everywhere, and will swiftly devour the entire plant. Given the legions of caterpillars, once the eggs are laid on the plant, the battle is lost. I tried row covers, but either I did not put them on at the right times or didn’t seal them up well enough. But even the plants that I did manage to get to maturity were scrawny things due to what I mentioned above.
I also tried growing lettuce, often in containers, but that can be a feat as the climate here seems uniquely suited to causing plants to bolt, sometimes to the point that flowers are forming before there are many leaves at all. I can certainly understand that, because spring usually only lasts a week or so here. It is usually a week where I start out wearing sweaters due to the freezing cold, and by the end of the week I am wearing shorts and putting in the air conditioners to tame the stifling heat.
Planting new seedlings was always an adventure. Besides the problem with all the roots in the bed that I mentioned earlier, squirrels are drawn to new plantings, and usually at least one plant will be dug out of the bed by the next morning, if I am lucky it is intact enough to replant. Apparently they do not realize that if they just waited a few months there would be small fruits which they could chew on or run off with (as they often do). One time I planted out my new seedlings, and as I was finishing the sky grew dark and it started raining, a total downpour. When I came out afterwards to check on the garden, I found all my seedlings were gone, pounded into oblivion.
I grew saffron for a couple of years, but digging up the bulbs is a challenge with all the roots to dig around, the last time I did so I found most of the bulbs dug up and/or eaten. It may not have been the squirrels, but with all the other damage they cause, I am not giving them the benefit of the doubt.
So the plants face quite a range of challenges, what about me? For most of the growing season it is very hot and humid, things that insects like. The mosquitos were relentless. So were the ticks (deer ticks with lyme disease, no less). I was bitten repeatedly despite bug spray, BTI laced traps, etc. Oh, and the poison ivy, which grows everywhere. The only thing left was a mechanical barrier. So I would have to wear jeans and long sleeve shirt, regardless of the weather and always plan to shower immediately afterwards. Tending to the garden was a time consuming ordeal, and, as such, didn’t happen as often as it should.
Can I say anything positive? I see many gardeners complaining about “weed pressure”, but weeds rarely caused me a problem. I suspect the weeds were smart enough not to grow in such an inhospitable place. And water was rarely an issue, usually it rained frequently enough so that I didn’t need to put extra water on the garden, but on the other hand, I think all this rain and lack of sunlight exacerbated the fungal diseases.
Let’s review: lack of sunlight, fungal diseases, insect pests, squirrels, woodchucks, deer, mosquitoes, ticks, tree roots, thin soil, horrible weather. The deck is stacked against me. I surrender.
Anybody who knows me, knows that I have tasten which run towards that which is obscure, unpopular, or simply forgotten. This is particularily true of music. In the late ’80s I discovered Phil Ochs and was so taken with his work that I created a web site as tribute to him.
One day (again, in the late ’80s) I spotted a small write up about a local band called The Riflebirds and that they were playing at the Dublin Pub. I was getting together with a bunch of friends and I talked them into going there for the next show. I was immediately taken with the band, and went out to buy their new album.
Sadly, the band broke up shortly afterwards. I think I went to their final show a few months later.
But I still listened to the tape, and had it sitting on my desk at work at the university.
One day a student came in and wanted to transfer his files onto floppies to take with him. My office mate was helping him do this and at one point the student saw the tape and asked “is this yours?” My office mate did not share my taste in music and, with a sneer, pointed at me and accusingly said, “No, it’s his”. The student then revealed that he was Kevin Kraft, the guitarist for The Riflebirds. We chatted for a bit, but I don’t know why I didn’t have him autograph my tape.
Many years later, I was at a John Wesley Harding concert in Seattle. When he introduced the band members I heard a name that rang a bell. After the concert, while getting a CD autographed, I asked the drummer if he was the same Kevin Jarvis who played with the Riflebirds. He seemed shocked that anybody remembered that.
But the tape has stayed in my collection, and periodically I would listen to it, and wonder what might have been.
One day, years ago, I searched for them on the web, which was a bit tricky as an Austrailian band by the same name started around 2014. And there it was! There were a few songs on ReverbNation including an extended version of their masterpiece “The Rain”. I absolutely love that song and now that I live far from Oregon it makes me miss both the band and my home state. I managed to (badly) digitize the tape so now I have it all on my phone. But I always wish I had more.
However, last week I get an email that they released a single, Sometime Somewhere (more versions at bandcamp) and an album will follow! This is the best news I have gotten for a long time! Go check them out!
I discovered that their new track is on Amazon music, and they force you to their shitty shuffle (I am writing up something about that) but in this case, after playing the Riflebirds it played Dar William’s song “As Cool As I Am” which was quite a coincidence, as I always thought Dar should do a cover of “The Rain”.
[Note: I had this article mostly written years ago, but never could think how to bring it to a close. But the band fixed that for me!]
Even though I was always interested in science fiction, I really never read very widely. I honestly cannot think of anything I read which was not connected to a TV show or movie (e.g. Star Trek, 2001, Hitchhikers Guide). After I started playing D&D I veered off into fantasy, which was most of my fiction reading for many years. As I have gotten older I have found that my diet of mainly non-fiction books was hard to maintain, so I now always try to have two books in progress: one non-fiction, and one fiction, when I get tired of reading the former, I will read the latter. This is a good strategy and has increased how many books I am able to get through. As such I have started reading older classic science fiction, many from Appendix N.
I don’t remember how, but a few years ago I happened upon the works of Clifford Simak. I read The Way Station and really liked it. It felt different from so much science fiction, it had a meditative pace and focused on the characters rather than on gadgets and guns. It was a beautiful story and I felt better having read it.
The first time I played D&D the DM put the giant map of the City State of the Invincible Overlord onto the table. That map was full of delicious details, and I wanted to be there. At that moment I was hooked on D&D. I studied every detail on that map, so, even after all these years, I remembered an odd detail: the area on the map labeled “goblin reservation”. Given that Simak’s book was published 8 years earlier, this cannot be a coincidence, I suspect that is an “Easter egg” and a homage to Simak. If anyone has any evidence to back up this conjecture, I am all ears.
I have just finished the book and it was a fun read. Simak clearly did not believe in the division between science fiction and fantasy, and he gleefully mixed them all up, but somehow still kept it a believable, compelling story. This mashup reminded me of some D&D adventures with similar genre jumbles, like the classic Expedition to the Barrier Peaks or some Judges Guild adventures.
Yet another coincidence is that Simak was born the same year as my grandmother, and both of them had fathers who emigrated from Bohemia. Further, he was born and raised in the same county where my grandmother also spent her early years (from 1910 to 1926) about 30 miles away from each other. Furthermore, when I saw his photo on Wikipedia, I was immediately saw a resemblance to my uncles on the Czech side of the family. But on the other hand, his mother descends from early settlers in New England, and it appears we are 9th cousins, maybe less. In the course of finding that, I noticed that one of his great uncles lived in Lake Geneva, WI.
So for all these reasons, I feel an odd connection with Simak, and his works will be on my to read list for some time. Let me know what I should read next.
Some time ago I had a long discussion with my father (someone who has a long history with cars starting with riding his father’s new Ford Model A) about the prospect of autonomous cars. I don’t have any particular knowledge on the topic, beyond working in an unrelated specialty of computer science. Though I do have experience being hit by a car. And I got a “C” in high-school auto shop class. So take everything I say with appropriate grains of salt.
I started out arguing that having a computer drive a car was a hopeless task. Think about what we have to do every time we drive: we have a multitude of different controls; we have to monitor other cars, pedestrians, bikes, animals, all moving in every direction; we have to monitor our location in the road and understand all the markings and signs to know where to go next. I am teaching my teenage daughter to drive, and I find more and more things to explain to her. There’s a reason we require them to practice with an adult in the car for quite a while before they can do this on their own.
Furthermore, I don’t have faith that we could even write software reliable enough to do all this. I have written about the sad state of software on this blog for many years. We all have to deal with lousy software every day. It should be self-evident that this is a problem.
Midway through this discussion I had a sudden realization: Humans are really awful at driving. I mean, really awful! We accept the fact that the most likely way for our children to die is due to a car. We just accept that cars will kill 40,000 each year (in the U.S.). The computer doesn’t have to be a perfect driver, just better than humans. The computer has a VERY low bar to clear. A computer isn’t going to drive drunk, or text while driving, or get road rage, or drive too fast on icy roads, etc. A computer may fail to notice a stop sign, or not notice the bicycle in the next lane, but humans do that ALL THE TIME!
Should we be terrified of getting into a autonomous car? Sure. Should we should also be terrified of getting in a car with Aunt Mildred? Absolutely! Or be afraid trying to walk across the street? Damn right!
The fundamental problem is that you have a ton of steel moving at high speeds to carry your (comparatively) tiny body from one place to another. It’s a waste of materials, resources, and lives, no matter who’s driving.
I think we have all heard the old story: A man asks a woman if she will sleep with him for a million dollars. Of course, she says yes. He then offers her two dollars and she gets mad, saying, ‘What do you think I am?’ He answers, ‘We know what you are. We are just haggling over the price.’
I think most people would agree that killing Hitler (or anybody else who has killed millions of people) would be justified. And, conversely, most of us would agree that killing someone who has done no harm to anybody is utterly unacceptable (though I can think of some police officers who would disagree).
So we know what sort of people we are, we’re just haggling over the price. How many people does one have to kill in order to justify killing someone? Was Brian Thompson responsible for enough deaths to justify his killing?
My answer is, of course, “no”. But for two reasons. First is that I decry any sort of violence and killing. I am vegan, so I am opposed to harm to any animal, not just humans. (People love to ask vegans silly hypotheticals, if you are tempted, go read some Gary Francione instead)
Secondly is the same reason I oppose the death penalty: Assuming they are guilty of the crime (which is sometimes not the case in this country) it is the easy way out for them, they will suffer for a few moments and then they are free of any consequence for what they did. But the victims and those they knew will continue to suffer for years. So I want the perpetrator to actually pay a penalty comensurate with the crime, to have to live in a tiny concrete room for the rest of their days, constantly reminded of what they have done.
Brian Thompson should not be dead. He should be in jail and stripped of his assets. Let him experience the medical bankruptly he inflicted. Let him put up a GoFundMe for his medical expenses. Maybe he should be forced to spend all his days on the phone with health insurance companies appealing claims denials. That would be a suitable community service for him.
However, thinking about all these denied insurance claims brings me back to the debate about Obamacare. I was particulary amused by the “death panel” myth. Amused? Yes, because we already have death panels! They are called health insurance companies. Their claims denials, for some, lead to death.
Assuming such decisions have to be made, I would prefer it to be made by a government agency. At least we have a nominal amount of control and accountability with such an agency via the ballot box and such. A private health insurance company has no accountability and no appeals; its sole purpose is to maximize profits, which logically, inevitably, leads to claims denials. The more the better.
I guess we can bring the claims denials back to that old joke (especially since I am not really qualified to discuss the nuance of this topic). Is 48.3 million denials (that’s 17%) too many? Is one? We’re just haggling over the price.
I would suggest reading Cory Doctorow’s post Predicting the Present. He is a much better writer.
Most of my childhood was on a farm. I experienced death all the time. When I was about 8, I was closing up the hen house for the night and found her, a small hen, sitting on the floor, rather than on the roosts like the rest, her head twisting in a gentle, spastic way. Though I was young, I could see she was in a bad way. I took her into the barn where my father was shoveling out the manure. I sat down on a bale of hay and held her. She could not move in any sensible way, she could not stand, and her head would slowly twist to the left, and then spring back to normal, and repeat. That got slower and slower until finally she slumped over, her wide-open eye staring vacantly towards the rafters. She didn’t even have a name, she was just one of the brown hens. I found a shoe box and my father helped me dig a hole by an old apple tree where we buried her. I don’t think there were any tears or grief, just a bit of sadness; just another day on the farm.
It would take me far too long to write about our entire life together, but I’ll give a few snippets. Write them down before the mists of time blur the memories beyond recall.
She was not a cuddly lap cat. I don’t think I heard her purr until she got much older. But she loved to curl up next to her humans more so as she got older. As long as it was on her terms. She would sleep pushed right up against my wife, but if I ever slept on my back, she loved to lay on top of my legs. After I took a shower in the morning, I would sit on the bed for a bit in my robe, and she would rush over, barely waiting for me to get in position before she trying to climb on top of me.
But the last few years were hard. She collected a number of maladies, one of which was a spinal issue which hindered her ability to walk, so she had a limp and one leg would thump when she walked. But even so, she would still chase her sister around (which was more fun for her than her sister), and she would still try to jump around in ways that was risky to impossible given her age. Her lack of flexibility eventually left her unable to groom herself. A few days ago her eating diminished to almost nothing and no amount of coaxing or bribing her with churu on her food would work. I knew this was a bad sign.
A couple of days into the Olympics, by step-son pointed out that the US had not won ANY medals in one event: shooting. I was shocked. For the United States the gun is the holiest of holy! How could we not get any medals? To my relief, in the subsequent days the US did win some medals, including a single gold, but we still placed third overall. What a tragedy!
I came to the conclusion that the structure of the existing Olympic event was not fully compatible with the gun culture in the United States. We should push to get a new event which would better reflect our true skills as a country. The event should take place in a large room, the targets scattered randomly in the room, some of them partly behind obstacles like desks, chairs, and tables. The targets should be smaller, maybe 4 feet tall. The goal would be to burst through the door and shoot as many targets as possible. There would be several rooms set up like this, and the goal is to go from room to room and shoot as many targets as possible in limited time (the average 911 response time). The firearms used would be limited to ones which can be legally purchased in the shooter’s country, which should further guarantee the US supremacy in the event.
I do hope you will all consider my Modest Proposal carefully; I feel this sort of event would truly showcase one of our greatest skills as a nation. We must not throw away our shot.
Many of us do not think much about school shootings, as we are often far removed from them. In my case, had I lived one mile to the east and had my daughter been one year older, she could have been in one of those classrooms at Sandy Hook. As such, I often paraphrase what Phil Ochs said about the events at the 1968 Democratic National Convention: “It doesn’t really matter if you were in Sandy Hook or not, because Sandy Hook is going to come everywhere in the US, and we will all get to meet Adam Lanza, in person, one way or the other.” (the original quote was in his intro to the song “William Butler Yeats Visits Lincoln Park and Escapes Unscathed” at a performance in Vancouver, 1968, listen here)
One of the unfortunate side effects of Moore’s Law is that the immense amounts of computing power at our fingertips masks over many horribly inefficient practices. For example, something I have commonly done for a very long time is use a sort, uniq, sort pipeline to tally up something; say you have a CSV containing users and the 2nd column is the country, so you want a quick list of how many you have from each country:
$ cat u | awk -F, '{print $2}' | sort | uniq -c | sort -n
1 ca
1 mx
14 in
16 us
Obviously for a short list that first sort is not expensive at all, but with my current laptop, I can do the same thing on a file with 2 million records and it finishes in 5 seconds, despite the massive sort. Obviously, this could be done using a O(n) algorithm like so (you could do this with Awk, of course, but I’m more fluent in Perl):
$ cat u | perl -ne '$a = (split(/,/))[1]; $c{$a}++; END { foreach my $i (sort {$c{$a}<=>$c{$b} } keys %c) { printf "%10d %s\n", $c{$i}, $i; } }'
1 ca
1 mx
14 in
16 us
(For those who have been through a job interview with me will recognize this question… few of you got it right)
Here’s a different example: When I was in high school the student government ran an annual fundraiser by doing a “computer dating” event: everyone would fill out a short multiple choice survey, and those would be sent off to some company to generate reports matching people.
One day, the computer teacher obliquely asked me if I could write a program that could take a list of people and randomly put together lists and generate reports. I knew what he was hinting at: let’s skip hiring the company and generate fake reports ourselves. I wrote that code, but, being a curious sort (and not entirely comfortable with the deception), I decided to try doing it the “right” way. The basic algorithm is simply to take a string of responses and match it against everyone else in the list, take the top ten matches and generate a report. Simple, right?
I worked on that program through the summer (keep in mind I was 16 writing in BASIC on an Apple ][), but I got it working. When we finally ran it on the full data set (a few hundred surveys), it sat and ran for over a week on an Apple ][ computer. [A personal note: since I was nursing this through, I saw every report slowly trickling out; my name came up on exactly one of those reports, and at number 7, at that. I was disappointed but not surprised.] We all know the same thing would, nowadays, be a few dozen lines of code and would run in seconds, despite being an O(n^2) algorithm.
So, this leads to the current problem. I was generating a report and I noticed that it was taking several minutes to run. That wasn’t a big deal, but my curiosity got the best of me, so I broke out a profiler and found this:
Holy cow! It makes sense as the source file has almost two million records, and I am parsing the date on every record. Who would have thought simple date parsing could take up so much time? I don’t know what I can do to make date parsing more efficient, but I did realize that I only need the date in some limited cases, so I changed the code to only do the date parsing at the time I actually need to compare timestamps, Changing this to lazy evaluation, bringing me into better alignment with the three virtues. The result:
Instead of parsing 1.8 million date entries, I now only parsed 82k.
Now, in my case, my code will never have to scale much beyond the current dataset, but if I did, there would be a catastrophe waiting to happen here.
The moral of the story is that we should all think about these seemingly minor decisions we make and think about what happens when the dataset scales up by orders of magnitude. That expensive sort or needless date parsing could hurt someday. Think about how your code will scale. Profile your code! You may discover things you didn’t expect.
I used to rant on here about awful error messages, but I kind of gave up as the problem kept getting worse. It seemed that error messages were getting less informative and error handling in code was getting worse. (I complained about this years ago) But here’s a cautionary tale about what the cost of this sloppiness can be.
So I inherited an internal service from another team, and one day I go to deploy an update, and the service will not start. I barely understand this thing or the language it is written in, and now I have to debug it!
At first I think the service is stuck trying to contact some external service which is gone. But after studying the error messages I find a cyclical nature to the errors: “starting service”, “starting subsystem x”, “starting subsystem y”, etc., “starting service”, repeating endlessly. So it is not hanging but crashing repeatedly with no error messages.
Now I come to the horrifying realization: If my service should go down for any reason, it will not start up again. I cannot patch the OS, or do anything which would cause a restart. If that happens, I will now have a crisis on my hands, and I don’t even know what is happening.
I poked around further and discovered that the on-disk logs had one more error message. I suppose this error did not make it out to the logging server before the service crashed. Sounds like another bug to me. But this error message was bewildering: “java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
” That makes no sense. First off, which database? The service connects to several. Secondly, the time between the previous log entry and this one is around 2 seconds; no sane person would set a timeout that short. I found a timeout setting which was, bewilderingly, set to 1 second! I changed it to 10 seconds. Now the time gap in the log was 20 seconds. I am not sure why it is off by a factor of two. Perhaps there are two attempts to connect, or there is a straight up math error.
Clearly there is something going wrong while connecting to the database, but that makes no sense: the database is running, and nothing has changed in any of the servers or network settings. That I know of. Better test it. The MySQL command line client gets through just fine. But maybe the library being used is at fault, so now I have to learn enough of this language to write a simple database client. Several hours later I have some code working. It works fine in every relevant context. So the “timeout” is, as I thought, a lie.
I dig through the stack trace and it seems whatever is going wrong is happening right here:
Connection out = driver().connect( jdbcUrl, properties );
if (out == null)
throw new SQLException("Apparently, jdbc URL '" + jdbcUrl + "' is not valid for the underlying " +
"driver [" + driver() + "].");
From the stack trace it is clear the exception is being thrown, but somewhere along the line that error message, as uninformative as it is (i.e. there is no indication of why it failed), is getting lost or suppressed.
Fortunately, one of the previous maintainers pointed out a way to enable more detailed logging. Miraculously, it revealed this error message:
java.sql.SQLException: The server time zone value 'UTC' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
So a fatal error is happening when connecting to the database. But that fatal error is suppressed unless debugging output is enabled. Let’s just pause and re-read the last sentence. Furthermore, the message from the other exception shown above is getting dropped along the way. But regardless a helpful article on Stack Overflow which pointed out a simple solution to add “serverTimezone=UTC” to the URL. Problem solved!
Two great mysteries remain: What changed in order to cause the timezone disagreement? My best guess is that an OS update changed some obscure timezone setting in such a way as to cause one of the servers to become confused about their timezone. The other mystery is why this fatal error was only sometimes fatal, and that “sometimes” became more and more likely as time went on, so early on, the service would restart repeatedly but then come up after some number of retries, eventually this became infinite.
But regardless, this illustrates the cost of sloppy error handling and uninformative error messages. I spent two full weeks clawing through source code trying to find the actual problem (the whole time in a panic that my production servers might get restarted and my service would be entirely down with no way to bring it back). But once the real error message was exposed the problem was fixed in minutes. That’s two weeks lost because someone couldn’t be bothered to do proper error reporting.
Every decision produces regret. Sometimes it isn’t a big thing or it is quickly forgotten. But for other decisions the thoughts of what might have been weighs heavily. I find that the older I get, the more I think about these things.
The year 2000 was a momentous year for me, the pivot of my entire life. I spent the previous year working hard fixing y2k bugs and trying to make my failing marriage work. Only one of those worked out, but, regardless, both were over. I am sure everyone has had a situation where you were working on a project frantically for a long time. But once you finish and the weight is suddenly lifted, you are confused. You haven’t had to think about what needs to be done for some time, but suddenly you do. This was where I found myself at the beginning of 2000.
I think my father sensed this and had a suggestion: let’s buy a boat. He had several boats when I was a kid, and we talked about boats ever since, often we would go down to the local marinas to look at boats for sale. I joined a local sailing club a few years earlier, but found that sailing in and out of the marina to “race the buoys” for a few hours was not what I was after and dropped out. I wanted to try longer trips to more remote places. I wasn’t interested in big boats or sailing on the ocean. I spent the first 33 years of my life within a mile or two of the Columbia River. It speaks to me. I wanted to explore.
Given the pending divorce, I had no money to spare, but he offered to pay for it. I didn’t want to spend too much of his money, and I also don’t like big boats. We very quickly settled on buying a West Wight Potter 15. So he called up the factory and within a month we were in Los Angeles picking up our newly built Potter.
When I was young, my father told me that the river was navigtable as far as Lewiston, Idaho. I always thought such a river trip would be amazing. Going upriver was far too arduous in a sailboat; the current in the Columbia river is often nearing the hull speed of a small sailboat. So unless there was a strong, favorable wind, going upriver was not something which could happen quickly. But downriver is a different matter. If you throw a stick in the river at Lewiston, by my calculation it would get to the ocean in less than a week. So if I don’t have the wind at my back, I’ll have the current pushing me forward. My employer had a generous “sabatical” policy, which let me take 4 weeks of vacation after 5 years of work. That should be plenty of time for such a voyage. I started planning the journey for the begining of September.
But being single is not something I was accustomed to. I was married young and promptly tried to find someone to fill that gap in my life. My divorce was proceeding at a snail’s pace, and here I am casting about for a relationship. We all know this will not end well. And it doesn’t. The first woman was truly insane, which I should have noticed after two dates, not after two months. Then I met a woman at a software conference. I immediately imagine I found my soul mate. But she lives in Maine. No problem! I have vacation time scheduled in September! I have some cash I was going to use on boat equipment! I spend a week with her further convincing myself that she is the one. I make plans to change jobs so I can move across the country. Within a year I am living in Boston, and within two years I am, again, alone because I did not have a cool house in northern Vermont. The tricky thing about soul-mates is that it isn’t always symmetrical: just because you find your soul-mate, does not mean the other person found theirs.
By that time my father had sold the boat, and I was stuck where I was. I got on with my life, and while I didn’t end up where I expected, I am happy with it (aside from what happened in the last paragraph).
But I always think about that trip, and wonder what it would have been like. One day I thought: why not imagine it had? Write a account of the journey: an imaginary memoir, a hallucinatory travelogue, a speculation of what might have been. I had many adventures in the final 115 miles of the Columbia. Cast those into the story, sometimes reformed to fit the narrative, others as a verbatim flashback. And make up the rest. I still have the river charts and, with the internet, I can virtually explore many of the places.
In the course of doing this, I was looking at various photos on Google Maps. Curiously, there is an island which is not on my charts: Kelly Bar. Presumably it was made in the last few decades from dredging operations. But someone shared two pictures from that island, both of them showed a West Wight Potter anchored in a sheltered spot. I take this as a sign. My Potter needs to make that journey. Even if it is only in my mind.
Another sign I should do this was in a recent episode of Sideways, where the host said:
“All of us unconciously choose what to remember and what to forget. Sometimes we edit and retouch our stories to make them more vivid or satisfying. And this is why failing to get the facts entirely correct is not unusual. It’s inevitable. And it’s also deeply, inextricably, human.”
I don’t know if I will ever finish this, or if anyone is interested, but I will share anything I deem good enough here.
I first learned to program when the primary mechanism of error handling was to check the return value of each function call and react appropriately. This often led to awful code where functions are called with no checking, and things mysteriously fail several steps removed from the actual error. Therefore I learned to add in lots of error handling so that any error messages would be very specific and easy to fix, to the point that I was once told I had too much error handling. Theoretically more modern programming languages with their try/catch syntax would help, but I am not convinced of that. syntactic sugar is no replacement for programmer discipline. Here’s a case in point, what’s the difference between this:
open(F, "$confdir/config")
$conf = parseconfig(<F>);
dbconnect($conf->{db}{uri}) or die;
and this:
try {
open(F, "$confdir/config")
$conf = parseconfig(<F>);
dbconnect($conf->{db}{uri});
catch {
die;
}
I can think of at least 6 ways this could fail, all yielding the exact same error, in either version. Don’t tell me you’ve never seen code like either one of those!
But, moving on from hypotheticals, here’s a simplified version of my code:
use Search::Elasticsearch;
my $e = Search::Elasticsearch->new( nodes => [$esurl]);
die "Error: unable to connect to $esurl\n" unless $e->ping;
print "connected to $esurl\n";
Running it gets this error:
[NoNodes] ** No nodes are available: [https://es.example.com:9200], called from sub Search::Elasticsearch::Role::Client::Direct::__ANON__ at foo.pl line 31.
Hmmm… neither my die or print generated any output; it is crashing the entire program while inside ping(). So this is my fault, I didn’t realize this module was written assuming try/catch blocks would be used, but doing that doesn’t really change much. The error message is the same; I still don’t know why it is failing. The server at the url works perfectly fine. So I dig in with the Perl debugger, and finally narrow down the crash to this line in HTTP::Tiny:
_croak(qq{$type URL must be in format http[s]://[auth@]<host>:<port>/\n});
That looks like a potentially helpful error message! It’s too bad it is getting lost somewhere along the way. Going up the call stack I come to this:
return HTTP::Tiny->new( %args, %{ $self->handle_args } );
No error handling, no try/catch, they just blindly create the HTTP::Tiny object and hope it all works. There are a number of try/catch blocks further up the stack, but the error message gets lost along the way, and by the time my catch happens, it is gone. I did discover that enabling detailed logging via “use Log::Any::Adapter qw(Stderr);” did yield that error message:
http_proxy URL must be in format http[s]://[auth@]<host>:<port>/
at /usr/local/share/perl5/Search/Elasticsearch/Cxn/HTTPTiny.pm line 86.
Proxy?! There shouldn’t be a proxy set! After some searching I finally find that someone kludged /etc/environment with the proxy. Obviously that was a bad idea. I never could figure out what was wrong with the proxy url, but since it should not have happened, and I had wasted at least an hour on this, I stopped digging.
So what went wrong here? First the error message says that the proxy url is invalid, but it doesn’t show me what that value was. Secondly, that real error message got lost somewhere along the way. This sort of sloppiness is what leads to many of the awful error messages I have documented here previously (like this), and trying to catch the exceptions doesn’t fix sloppy code.
A few weeks ago I listened to Mike Shea talk about running a Ravenloft “funnel” for Halloween. And around the same time one of the players in my newly started Drakkenheim campaign had written up an elaborate backstory which had his character escaping from Drakkenheim as the meteor hit the city. As with peanut butter and chocolate, these two should go together quite well.
So first I need a way to generate a bunch of level 0 A5E characters. I have done some searching, but have not found anything yet. I may end up writing a tool, stay tuned.
I will do more research but it seems that it would go like this: have a pile of pregenerated characters, hand out one to each player. Roll initiative, the entire thing will be done in rounds (much like Shadowdark).
I am still trying to decide if I should have just one giant table, or split it apart into a table of encounters and a table of scenery. I am leaning towards the former in the interests of simplicity: one roll each round. But regardless, roll d100 plus the number of rounds played. The encounter table will be laid out to escalate, more difficult encounters are located at the end of the table, which will obviously go well past 100. Paint the scene, and run the encounter.
If a character dies, the player will grab a new one, and play proceeds.
Lather, Rinse, Repeat.
I was thinking of various ways to track progress towards a goal, but I have concluded the best way to do this is to set a real world timer. When that timer goes off, finish the current encounter, you have reached the city gates and have gotten to safety! You could measure the “success” of the game by counting how many rounds it took, the body count, or how many rounds each character survived.
I have a spreadsheet I am using to collect ideas for the encounter table. Suggestions welcome!
So I just ran into a piece of code which looked something like this
request = http.request(someurl)
if (request.status == 200)
{
mystuff = request.body.foo
}
I showed this to my wife, who knows almost nothing about code. She said “what if it gets a status other than 200?” Despite the fact that her one and only coding class was in high school and she barely remembers it, she has managed to do better than the veteran who wrote that code! I responded, “Well, at least they are checking for the status rather than blindly proceeding!” I should not have said that. Fifteen minutes later, in the same file, I ran into code which was like this:
request = http.request(someurl)
mystuff = request.body.foo
Larry Niven once said “That’s the thing about people who think they hate computers … What they really hate is lousy programmers.”
So after finishing Cory Doctorow’s book I have been thinking about all the enshittified platforms I have been entangled with and how to reduce my dependence on them. Then I start thinking about how they tricked me into these situations. And then I thought about the OGL debacle (here are my earlier ruminations on the topic), and how badly WotC mishandled things with respect to “monetizing” the brand. It seems like the enshittification playbook has been demonstrated repeatedly, so it was a colossal failure on the part of management there.
Here’s the way it should have gone:
[Since I started writing this, I heard an owner of a game shop pointing out that the digital bundles are a total rugpull against them. If most people will want to get access to the books on D&D Beyond, why buy them separately? The only reason you would go to the game shop is to get the special covers. This is some late-stage enshittification: “…abuse those business customers to claw back all the value for themselves.” Good job!]
I am not sure if “OneD&D” complicates this picture or not. I think the key for rolling that out is to ensure the platform works equally well for 5th and 6th edition, and then just put the new books up for sale. Make it easy to switch over, and, for now, make it easy to stay with 5th edition. Make sure to keep the revenue flowing for 5th edition. It would be tempting to force people to the new edition, but you do want to make sure the effort to switch to the new edition is really trivial (once the requisite amount of money has been spent). But which edition is in use is kind of irrelevant as long as the monthly membership fees keep flowing.
Before the OGL Debacle, I was on the verge of buying a source book bundle and a paid membership on D&D Beyond. I was even reading the playtests packets for the next edition. If they had followed the above strategy, instead of burning a whole lot of goodwill, I would have been fully committed to the platform as they rolled out the above strategy. At some point I may have caught on, but by the time I did, the switching costs would have been quite high and I may have begrudgingly stuck with it, as I am doing right now with Amazon and Google. And even if I did work up the gumption to cancel my subscription, I would have been virtually alone. And where could I have gone? Without the OGL debacle, there would have been far fewer alternatives, there wouldn’t have been Project Black Flag or C7D20, and maybe Level Up A5E would have dried up.
So it is really mind-boggling that they blundered to the degree they did, especially since several of the executives at Hasbro came from Microsoft which is the pioneer of building tech monopolies via shitty business practices. Had they been patient and careful, they could have dominated the entire industry.
Trying to think like an evil genius has made me feel kind of dirty. I think I’ll go take a shower and get back to planning my Level Up A5E campaign.