After more than fifteen years of loyal LiveJournal use, I have switched to Dreamwidth as my primary blogging site. All of my LiveJournal entries have been migrated to flwyd.dreamwidth.org. They remain public on flwyd.livejournal.com as well, so as not to break any links. I will continue crossposting from Dreamwidth to LiveJournal until LJ blocks it, or until the site owners do something egregious with regards to user content.
Shout out to brad and everyone else who helped make LiveJournal a fantastic social network before "social network" was a thing. The most important asset of a site like this is the users and their willingness to share with each other. Over the last decade, a lot of user attention has drifted to other platforms. The management (now headquartered in Russia) has also focused on writers of the Cyrillic persuasion and Russians in particular, burning the trust of the Anglophone user base.
Advent of Code is an annual programming challenge. Every night at midnight EST from December 1st through 25th, a new problem is posted to the website, along with a participant-specific input file. Participants can use any programming language they want to solve the problem, using their input, and see if the output of their program matches the expected value. Once that's done, a second part of the problem becomes available. Part 2 uses the same input file and is generally a variation on the first part, such as changing the goal from "find the maximum" to "find the sum of all" or increasing the number of times an operation needs to be performed so that an inefficient algorithm will be far too slow. Problems are usually straightforward at the beginning of the month and get more challenging as the month progresses. There's a stats page measuring time-to-completion and a top-100 leaderboard, but no prizes; many folks pursue their own goals like learning a new language or minimizing program runtime which are somewhat at odds with quick finishes.
After having lots of fun and learning Kotlin with Advent of Code in December 2020, I decided to use Raku for this past year's edition (with code shared on GitHub). Raku is the new name of Perl 6, a "member of the Perl family of languages" which famously took a decade and a half of community experimentation before a finalized version was released. Perl, in turn, is a language originally focused on working with collections of text files which is famously easy to write or hard to read, depending on who you ask. Raku keeps many of Perl's basic syntactic elements—like scalar, array, and hash variables identified by $, @, and % sigils—but also brings to bear a lot of modern programming language developments like class-based object orientation, concurrency, type constraints, multi-dispatch, and just-in-time compilation. Raku is also what one might call Unicode-forward. Most languages these days allow Unicode literals in strings, and most languages made since the '90s allow Unicode letters in program identifiers. Raku takes this significantly further. First, Raku strings are sequences of graphemes rather than just bytes or Unicode code points, so both the single-code-point and the "combining diacritics" variants of "é" are identical in Raku. Second, Unicode characters aren't just limited to letters: the language and standard library provide $thing ∈ ($set1 ∪ $set2) for set operations, @words».uc to upper-case each element of an array, ⚛++ for atomic-increment, 25 ** ½ as another way to perform a square root, and quoting strings with arbitrary characters like say q༺hello world༻.uc. Additionally, Raku took one of Perl's big selling points in the '80s and '90s (terse and powerful regular expressions) and evolved them into grammars which are easier to read, modify, and compose, and likely also faster. This grammar support is what drew my interest to Raku, since I started a hobby project that involves parsing a small amount of information from source code written in a large number of languages, and the ability to quickly write but still maintain textual matchers would make that project more pleasant.
One of the driving principles in the design of Raku (and Perl before it) is There's more than one way to do it (TMTOWTDI). Another principle (repeated frequently by people who post in help forums, it seems) is that programming in Raku should be fun. Several times while working on an Advent of Code solution I tried to do something in a way that looked both elegant and reasonable, only to find out that There's More Than One Way To Do It, But Some Of Those Ways Are Wrong. (Furthermore, since TMTOWTDI, the documentation usually doesn't say "This isn't a good tool for X, use Y instead.") For example, I spent at least half an hour trying to understand why my memoization code didn't seem to be caching my Pair objects, despite all my experiments with the interactive interpreter looking like things should work just fine. It turns out that foo => 42 creates a Pair which uses value equality for both key and value, but my $key = 'foo'; my $val = 42; $key => $val creates a Pair that holds on to the $val scalar (but not the key scalar) and thus uses (half) reference equality. The documentation explains this behavior in an aside and explains that .freeze will result in an immutable Pair, but it's easy to encounter Pairs in documentation that doesn't mention that, and the half hour of WTF was not at all fun. (Another Way To Do It would be implementing a 2-value tuple class myself, which wouldn't have added fancypants scalar handling.) This discovery also reduced my confidence in the language a bit: when I look at a block of code, am I sure that my variables work as values, or might something else hold on to this funny scalar reference?
Another un-fun discovery was that for @first ∩ @second { … } doesn't iterate through the shared elements of two arrays, but instead iterates through Pairs, where the value is always True. I was aware that many set implementations are implemented as a hash table where the keys are set elements and the values are a placeholder value like a boolean. But most languages hide this implementation detail and present a set as akin to an unordered list which doesn't allow duplicate values. The workaround is easy (call .keys on the set when iterating over it), and it provides a nice symmetry with Bags (multisets) and Mixes (weighted sets), but it was still a big surprise. This was made worse by Raku's gradual typing discipline and implicit conversions; I think I was putting the set elements into a Hash, which converts keys to strings by default, so rather than a compile or runtime error complaining that I was using a Pair where a Str was expected I got a Hash with keys like foo<tab>True rather than just foo. Iteration and automatic conversion also combine in un-fun ways because the base class for most objects implements all the List methods by converting non-iterable objects into single-element lists. I would find it a lot more fun if the Raku compiler would tell me that sub answer(--> Int) { 42 } ; for answer() { … } was attempting to iterate over a non-iterable (maybe I changed answer from a List to an Int and forgot to update all the callers) rather than silently iterating over a single element. This annoyance is compounded by the fact that scalar references to iterable types (like a sequence, list, or array) are turned into single-element lists in this context, so changing my $x = nums => (1, 2, 3, 4); .say for $x.value (which prints four lines with one number each) to my $x = (1, 2, 3, 4); .say for $x changes the output to print a single line with four numbers and a pair of parentheses. This makes changing the shape of data structures while developing a program (like adding or removing a wrapper class) create surprising effects that aren't caught by the compiler. And maybe it's just me, but I think programming is more fun when the computer quickly tells you when you make a mistake, rather than losing an hour of sleep because you were debugging code that looked reasonable.
Working in Raku did have some fun elements. Contrary to my complaints about automatic conversions for container types, the ability to seamlessly work with numbers parsed from text was pretty nice for Advent of Code problems. Having a Complex number type that works as a hash key made several 2D grid traversal problems fairly convenient. And I even got to leverage Raku's nice Unicode property support on a problem about open/close punctuation balancing. I opted to use Raku this year as a way to try out grammars, and they were generally nice. They're way more readable than Perl regular expressions and the "Perl-compatible" regex implementations that have come along in the past three decades, and the ability to supply an Actions class to parse the relevant data from a match and bubble it up makes working with the result of a complex parse much nicer. Grammars are generally overkill for AoC inputs, but I found the structure pretty nice. The one downside to Raku grammars was the lack of helpful information when a parse failed. Unlike a typical programming language compiler that outputs the line and column where input didn't match expectations, a failed grammar parse just returns null, even though Raku has a Failure type that allows conveying additional information. So when my parsing rules were wrong I generally had to put output statements in the Action class and manually inspect what the next token should've been.
Contrary to last year, when I mostly focused on implementing the code and learning the language, I spent a lot of time on the social side of AoC this year. Last year I participated a bit in the Reddit community to provide hints to folks who were stuck. This year, after solving the problem and then participating in Google's group chat about the day's challenge, I frequently spent a couple hours on Reddit, reading through the "solutions megathread" and checking out people's visualizations. This meant a lot of 3am bedtimes this December, followed by another late night. Coupled with trying to actually get some work done, I spent far too much time staring at a screen this December. Also, unlike 2020, there were social reasons to leave the house this year—friends were amused that I was programming in Vim over SSH from a smartphone while semi-drunk at a holiday party while also chatting with folks. (There were just a couple small bugs by the time I got home, and Vim's terse modal editing proved to be a nicer phone-based development environment than I'd expected.)
Three weeks of late nights—including an all-nigher for day 19 because I'd incorrectly assumed that rotations in 3D were commutative—definitely caught up with me. I was pretty burned out by the time I got stuck and went to bed on day 23, which is kind of an interesting problems with a lot of little fussy ways to introduce bugs. I was extra toasty on day 24 (the night leading into Christmas Eve) when I discovered that what I thought would be a reasonable solution—a modified binary search—didn't work at all because in the possible solution space of about 20 trillion numbers, fewer than ten are even potentially the right answer. This fact about the input file wasn't at all clear from the problem statement, and the frustration was intensified by the fact that (contrary to every other AoC problem I've seen) there was no realistic example and expected output to experiment with. The fact that a seemingly reasonable solution can run for hours without providing any insight about the problem (other than "valid values are sparse") and that (as far as I can tell) an efficient solution to this otherwise NP-complete problem requires making assumptions based on a single input file, pretty much soured me on what had otherwise been an enjoyable month. That one day's problem (following a couple late nights) made me strongly question ever participating in "live" (i.e. during December) AoC ever again, which isn't a good feeling to have on Christmas Eve.
Raku's final un-fun factor played a role in this burnout too: slow execution speed. I'd seen folks who hang out on Raku help communities warn folks that Raku performance isn't great, but I figured it would be fine for Advent of Code, which has lots of folks working in languages like Python and more tortured environments like Bash or Google Sheets. But on days 19, 23, and 24 I discovered that my Raku code would spend tens of minutes running on the example input before producing a wrong answer, which is not a good situation in a "implement a program before bedtime" challenge. To more quickly test wrong hypotheses and spot bugs, I reimplemented those days in Go. The Go language is far more verbose and has many fewer features than Raku, but I could implement a Go solution and try it five times in the time it would take to run my Raku code twice. My day 19 solution in Go—using the same algorithm and only slightly optimized code paths—was about a hundred times faster than the Raku implementation. I recall noticing that one Go run took 45 seconds while Raku took 45 minutes. I spent more time optimizing the runtime of the day 23 solution (due to some discussion in the group chat at work) and ended up with a 2.5 second solution in Go and a 68 minute solution in Raku. I even spent some time with the Raku profiler (which amusingly produced about a gigabyte of output for 45 seconds of runtime and had to be analyzed with sqlite because the HTML profiler output crashes any browser tab) and was only able to get a maximum 10% speedup after playing with all of the hot code paths under my control. Two orders of magnitude in runtime is difficult to make up with even the most amazing language expressiveness.
A popular casual topic of discussion the last few weeks has been that the Front Range has never gone this long without getting the first snow. Since October we've had two or three overnight dustings without any measurable accumulation. We've had far more unseasonably warm days, with plenty of "Mid-sixties and sunny" T-shirt weather in mid-December.
Weather forecasters predicted a big snow on New Year's Eve. The snow rode in on the tails of a big wind storm, with gusts in some places over 100 miles per hour. Last week also featured 100+ MPH gusts at the airport in Broomfield and other topologically ripe locations. Unfortunately, this week's gusts reportedly knocked down some power lines near Marshall Mesa which sparked fires in unusually dry grass—extra dry because we haven't had any snow since April, natch. The strong winds quickly pushed the fire eastward through open space, forcing the evacuation of the towns of Superior and Louisville. Wind pushed fire onto houses and through neighborhoods; emergency officials estimate that more than 500 homes were burned. This makes it the most structure-destructive fire in Colorado history, despite being far smaller than the month-long major forest fires we've seen in the past. A lot of affected residents probably wouldn't have thought of themselves as in the Wildland-urban interface; while many of the affected neighborhoods are next to open space, the fire also jumped the highway and burnt houses where the closest thing to a wild space is a greenbelt along a creek.
Fortunately, the forecast snow arrived this morning, dousing the fires and bringing the first significant moisture to the area in several months. This is now the second year in a row that a fire burning within a couple miles of our family's dwellings was extinguished by snow; the East Troublesome Fire last November climbed over the Continental Divide and got close to our family's cabin near Estes Park. While a dry final three months of the year and unseasonably warm December days aren't uncommon in Colorado, recent years have escalated the dry weather and unpredictable precipitation or lack thereof.
We were unaware of the fire for most of the day yesterday. I took the day off work and joined Kelly's family for a visit to Meow Wolf in Denver. It's sort of what you might get if Dr. Seuss and Burning Man teamed up to make an interactive art museum. Driving to an errand in Commerce City we noticed the huge wall of smoke stretching across the north Denver metro area. For quite awhile I thought it was probably dust getting kicked up by the strong winds; the colors and patterns in the clouds didn't look like wildfire smoke to me. I guess I'm just used to tree smoke coming over the mountains; a grass and suburb fire has a much different character. US-36 was closed from Broomfield, and we wanted to stop at the Asian grocery store there for some supplies anyway. Not knowing whether we had power or any wind damage at our home in Boulder, we decided it would be best to face the unknown with a full stomach, so we stuck around for pho and boba.
Driving home along US-287 through Broomfield we caught some glimpses of burning fires in the darkness of night, with cars lining several streets so folks could get a look. It's a sight I've seen before, but never in late December. As we approached home we drove through some blackout neighborhoods, but drew hope when the part of Arapahoe near our house was lit up. As we pulled onto the street we could tell luck was not in our favor, as we routed around two utility trucks parked next to a large tree in the middle of the road, and the whole block was dark, save for a few houses with a solar+battery system, keeping the holiday lights shining. Our neighbor gave us a quick update: several trees around our house had fallen, including a few that took down power lines. The neighbors right behind us had a tree uproot (falling away from the fence, and also not endangering their house), and a power line got hit by a tree crossing our next-door neighbor's house. We took a walk around the block in an odd mix of serene quiet mixed with occasional bright spotlights from utility trucks. A neighbor down the street had a tall blue spruce uproot and fall across their yard and driveway, and our neighbors across the street said one of their trees narrowly missed a service vehicle that afternoon. Our house came through pretty well; our glass patio table flipped over and landed 15 feet away from its starting position, but doesn't seem to have cracked. One of our sheds had the latch tear off and then the door got jammed stuck inside, but other than that we just had a lot of sticks littering the yard.
Being practiced Burners and festival attendees, we had plenty of flashlights on hand. I even picked up a 100 amp-hour LiFePo4 battery this fall to power Kelly's CPAP while camping, so I charged our phones and listened to both local FM radio and the local amateur radio emergency response channel on my ham radio. We gathered important items in case we needed to evacuate overnight and otherwise took it easy in the dark. The battery+CPAP setup worked like a charm; I didn't expect to use it at home before giving it a run in a tent. Power came back at 4:15 in the morning (shout out to the hard-working Xcel Energy crews) and New Year's Eve brought the wet snow we've been needing all month.
Hearts out to my friends and coworkers who live in Superior and Louisville, and may everyone's 2022 be a lot more chill.
Ain't found a way to kill me yet Spicy food still makes me sweat Every weekend I just go nowhere Safe at home with my new pet Hydroxychloroquine was no safe bet Spike proteins assail me from somewhere
Here they come to give the booster Yeah, here come the booster You know I ain't gonna die No, no, no, you know I ain't gonna die
Here they come to stab the booster, ah yeah Yeah, here come the booster, yeah You know I ain't gonna die No, no, no, you know I ain't gonna die
Feelin' fine, glad you asked They spit on me, I wear a mask Doctor sent me results from my swab Got my shots 'gainst covid death My buddy's breathin' his dyin' breath Oh RNA, please won't you help me make it through?
Here they come to give the booster Yeah, here come the booster, yeah You know I ain't gonna die No, no, no you know I ain't gonna die
Since July, supporters of carbon pricing have made nearly 160,000 contacts to Congress and the White house on this topic. There's been lots of talk about carbon pricing in negotiations on The Hill, and lots of folks have endorsed the idea. It's not currently part of the reconciliation bill framework that Joe Biden announced last week or that the House is working with, but there's still an opportunity to get it in the Senate bill. Anyone who lives in a state with a Democratic Senator can help this happen: the more support (say) Senators Michael Bennet and John Hickenlooper hear for carbon pricing, the more they'll be willing to push for it in negotiations with Senators like Joe Manchin who are on the fence. Democratic Representatives also need to hear that it's popular in their district so they're on board if a carbon price is part of the final bill.
Amateur radio enthusiasts sometimes organize a "fox hunt." A radio transmitter in an undisclosed location periodically broadcasts a signal on some frequency and participants use a directional antenna, a compass, and other tools to triangulate the transmitter's location.
Yesterday, the Boulder Amateur Radio Club organized a bit of a "reverse fox hunt." Two weeks ago, some club members noticed some unexpected transmissions on the club's VHF repeater from radio operators that were not also listening to that frequency. Someone was able to track down someone who'd made some of those transmissions and found that they had an AllStar hotspot operating on UHF simplex frequency 446.175 MHz. A hotspot in an amateur radio context is a low-power transceiver that's connected via the Internet to a wide-area digital radio network. The hot spot listens to a simplex frequency, sending anything it receives to the network. Likewise, any transmissions from the network are rebroadcast on the simplex frequency by the hotspot. This allows someone, perhaps the owner of the hotspot, to talk with people all over the world using a mobile or handheld radio that would normally only reach the local area.
The hotspot owner changed the frequency it was operating on. This stopped the stream of AllStar network chatter on the Boulder repeater, but this wasn't the root problem. Club members continued to notice occasional transmissions from 446.175 coming through on the repeater's frequency, suggesting that someone else was running a cross-band repeater with UHF input and VHF output on the club repeater's 146.100 MHz input frequency.
So some club members organized a "reverse fox hunt." Rather than listening for periodic transmissions from the "fox" we wanted to find locations where we could trigger the cross-band repeater, then triangulate its location. (I assume the final step would be "Knock on the nearest door and see if they're a ham operator.) Five of us gathered in the NCAR parking lot early Saturday afternoon. We weren't able to trip the cross-band repeater from NCAR, which has line of sight to all of Boulder, so we concluded that the fox was either over the hill in the Denver area or wasn't out of its foxhole that day. When the cross-band repeater had been active, we were able to get reports that it got triggered from Denver's Stapleton neighborhood and from an antenna on a mountain near Coal Creek Canyon.
We split up, sending one person to the Coal Creek area, one to Stapleton, one to Federal Heights, and one to Arvada. I headed down to Green Mountain, which was my favorite vantage point over metro Denver when I lived in Jefferson County. I transmitted from a few spots on the trail, neither of which lit up the Boulder repeater. One of our group had wondered if the cross-band repeater might be configured with a PL code&emdash;a tone of a particular frequency which must be transmitted along with the FM wave in order to activate a repeater to make it less likely to accidentally rebroadcast a message you didn't intend to. So I spent about half an hour turning the knob on my radio and making test transmissions with each possible squelch tone.
In the end, we concluded that the fox didn't come out to play yesterday, and we haven't noticed any spurious transmissions on the Boulder repeater this week. But playing radio was a pretty good excuse to go for a hike on a gorgeous late October afternoon, even if I didn't get to play with the directional yagi antenna I borrowed from a coworker.
For many years I've assumed that when I turned 42 I would throw a big party, invite a bunch of hoopy froods, and see if everyone knew where their towel was. As it turned out this week, I had about 2000 people at my birthday party, I didn't have to plan the event, and I didn't see many towels.
Element 11 is a long-standing regional Burning Man event in the Utah desert. It's normally held in July or June, which tend to be prime busy-in-Colorado times, particularly since Apogaea—Colorado's regional burn—is the second weekend of June. This year the organizers moved Element 11 to the last weekend of September, maximizing the amount of planning time in a year of chaos, minimizing the number of excuses for people to not be fully vaccinated, and balancing days which aren't too hot with nights that aren't too cold. Since Burning Man itself was cancelled and I didn't want to go to Plan B/Renegade Burn, I figured I'd have plenty of spoons for a regional in another state. Plus, I didn't have to plan a complicated themed birthday party.
It felt really good to be able to wander around, meet strangers, give hugs, dance to big sound, and share food. So far, it seems the policy of "proof of vaccination or a recent negative COVID test" was successful as I haven't heard that there was any COVID spread at the event. The fact that almost everything was outside certainly helped. I've now got a bit of a scratchy throat and some sore body parts, but my home-COVID test was negative, so I think this is just my immune system having forgotten how to deal with other people's garden variety germs, plus a depleted sleep schedule. I feel significantly less lousy than I did after getting back from a summer road trip.
The month leading up to the event was pretty jam-packed. I spent a bunch of time researching and ordering components for a solar and battery system so that Kelly could sleep with a CPAP, but I didn't give myself enough lead time and the project failed to come together before the trip, culminating in a comedy of errors including a brand new multimeter that needed aluminum foil shoved in the battery compartment in order to operate. Fortunately I've now got months to get things right and up my electrical game before our next camping adventure.
In addition to wrangling electrical components I spent a lot of time in the last month and a half playing with Colorado Redistricting Commission maps. The state has a new citizen-focused redistricting process, ideally reducing the political maneuvering involved, and anyone could submit their own maps and comments. I'm disappointed the commission and staff didn't follow my advice to (a) split census blocks in more natural ways so that neighbors stay in the same district and (b) allow slight variance (order of hundreds) in district size, following the "must be justified" portion of the law. Overall, though, the process seemed to work really well, and almost everyone at the hearings I attended was polite and on-topic, a rarity in the political world these days. There were a lot of "We don't want to be in a district with those people" comments, which make me sad as a collaborationist, but are understandable given the trend in the last half century for people to self-segregate politically.
I also spent a bunch of energy the weekend before Element 11 first picking apples and then helping press them into cider. We ended up with way more fruit than we could process and at the end of the day had more liquid than anyone could take away, particularly when the cooling system failed a few days later. I've got a cider brewing with wine yeast and a cyser (honey + apples) brewing with ale yeast; I'm hoping these turn out better than my last round of cyser which—three years later—still has a harsh flavor. This was a total blast, but cut way down on event packing and prep time.
After over a decade, the time has finally come… someone sent me an email encrypted with my PGP public key.
Based on the timestamp on my website, I set up GnuPG in 2007, which is two computers and about four hard drives ago. And while I'm a digital pack rat, those were the days that "copy your entire old computer to your new computer" would still cramp your new computer's space. So I would manually copy the home directory contents I knew I'd want like Documents and .vimrc but I probably didn't notice my private key file.
So for more than a decade I've been advertising a way to send me an email that no one can intercept and decrypt… including myself. 🤦♂️
I’d like to ask you for a favor. Feel free to say no :-) Please take five minutes to email or call your two U.S. Senators and ask them to support carbon pricing. If you don’t have your senators on speed dial, a group I volunteer with has a tool to make this an easy contact. Just visit cclusa.org/senate
If you’re contacting a Democratic senator, please ask them to put a price on carbon in this year’s budget reconciliation. This is the most likely path for ambitious climate legislation this year, and Democrats are in the driver’s seat. If you’re contacting a Republican senator, please ask them to support putting a price on carbon this year, because it will address climate change while strengthening the U.S. economy. While the Republican party is a little behind the Democrats on bold climate action, several GOP senators have voiced support for carbon pricing. It’s a policy they can support without losing their conservative credentials.
If you’re feeling unsure about calling Congress, I’ve shared a video of me making the call. I’ve always felt awkward on the phone, and if I can do it so can you! Pro tip: if you call after business hours you can leave a voicemail, and your support will still be noticed.
If you’re able to send two emails or make two calls, THANK YOU! If you’d like some extra credit, ask at least three friends to call their senators. Feel free to forward this post to them if you’d like. Support from constituents gives senators and representatives the reassurance they need to do what’s right, and I’ve spent a lot of energy in the last five years focused on demonstrating to Congress that carbon pricing is popular. Your email or call to your Senator means a lot to me. You rock!
If you’d like to learn a little more about carbon pricing, here’s my quick explainer:
When historians write the history of the 2020s, how America responded to climate change at the beginning of the decade will play a big role. We face big challenges associated with the climate, and big action is needed to stop greenhouse gas pollution. The current U.S. Congress is in the best position in over ten years to ensure the biggest emitters shift course and drastically reduce their use of fossil fuels.
A price on carbon is one effective way to quickly reduce greenhouse gas pollution. A carbon fee would be assessed on coal, oil, and natural gas; low at first, but getting bigger every year. This will create an incentive to switch to cleaner forms of energy; companies that switch to clean power will be able to outcompete those who pollute more. The impact of higher fossil fuel prices on lower income folks can be offset by a carbon dividend: the collected fees are divided into equal amounts and distributed to every American each month. Since folks with lower incomes usually have a much smaller carbon footprint than people and companies who can afford to consume more, the carbon dividend is an effective way to make polluters pay to solve the problem while protecting folks who would otherwise have trouble with higher energy prices. Finally, to prevent businesses from just shipping carbon pollution (and jobs) to other countries, a carbon border adjustment can apply the carbon fee to imports from countries which don’t have a carbon price, and rebate the fee paid by U.S. exporters shipping to those countries. This incentivizes other countries around the world to adopt a carbon price to stay competitive. In fact, the E.U. just announced details of their carbon border adjustment, which has inspired China to step up the pace of their own carbon pricing plans. That’s right, the U.S. is currently lagging China in adoption of the most effective solution to climate change.
This idea has broad support: IPCC scientists report that a strong price on carbon will be necessary to keep the world below 1.5 degrees warming. Over 3500 economists—liberal, conservative, progressive, and libertarian—have endorsed the carbon fee & dividend plan, the biggest joint statement in the history of the profession. Recent editorials in major newspapers have called on Congress to pass a carbon price. More than 1000 businesses, plus hundreds of nonprofits, faith groups, and local governments, have endorsed the Energy Innovation and Carbon Dividend Act, which could be the language used in a budget reconciliation bill.
For the past four and a half years I’ve volunteered with Citizens’ Climate Lobby, the largest carbon pricing advocacy group in the country—and probably the world. We educate the public and community leaders about the benefits of the carbon fee & dividend approach and the importance of climate action, and have gathered support from over 200,000 people around the world. CCL organizes several meetings each year with every Congressional office. In the last year and a half, thousands of people have been empowered to lobby their own Member of Congress via videoconference or over the phone. I’ve found lobby meetings with Congressional staff to be very personally rewarding. I truly believe that action on climate change can help bring a politically fractured America closer together so that we can collaborate on the big challenges of the 2020s. Behind closed doors there’s more interest in tackling these problems than you might think if you watch cable TV.
If you’re a fan of different climate solutions, that’s great! There’s lots of work to be done over the next three decades if we want to “hang on to the holocene” as Adam Frank put it. We need to pivot our electrical system, rethink transportation, improve millions of buildings, restore forests, shift agricultural practices, invent new technology, and build resilient communities, all while responding to emergencies and addressing injustice. I’m excited about carbon pricing because it’s the biggest step we can take, and it affects several emission sources at once, and it’s compatible with and complimentary to most other climate solutions. If regenerative agriculture or ending fugitive methane emissions are more up your alley, that’s awesome. To solve climate change we need a diverse team with a lot of specialized skills and interests.
When communicating over a noisy voice channel, like a two-way radio or a poor phone connection, it's useful to using a spelling alphabet to make key words extra clear. While many people on the phone use the first English name that comes to mind ("P as in Peter, H as in Harold, O as in Olivia, N as in Nancy, E as in Eve"), the lack of a standard set leaves plenty of room for confusion ("was that Eve or Steve?"). Most radio protocols standardize on the NATO phonetic alphabet. But if you want to have a little fun, I've provided an updated alphabet that is just slightly out of tune.
Alfalfa Bravado Charlene Deltoid Eco Faux pas Gulf Hostel Indiana Jeweled hat Killer Llama Mic No number Otter Popcorn Québécois Roaming Sarah Tangle Unicorn Victory Whisked X rated Yanking Zoro
In April, Burning Man announced that Black Rock City would not be built in 2021. I'd been holding out hope that the COVID recovery would be looking promising enough to make the event possible, and I'd been mentally preparing to spend a couple weeks wearing fashionable dust masks and experimenting with post-pandemic community creation.
My first world problem then turned to "What can I spend my big pile of accumulated vacation hours on now?" Early last year Google extended the unused vacation cap from 240 hours to 300 hours, since encouraging people to take a vacation when everyone was supposed to stay at home would've been irresponsible. I took a couple long weekends last summer, but between an "Avoid interacting with too many people" pandemic and "The western U.S. is blanketed in smoke, so visiting the mountains is no fun" there wasn't much worth spending vacation time on. As winter approached, I realized I was going to hit the cap before the weather was nice enough to run around outside, so I focused on long weekends of "Do stuff around the house." Between holidays and well-placed vacation days, I didn't have a five-day work week between mid-December and late February, which was fairly pleasant.
But now that summer has arrived, I decided it's time to have a big ol' vacation. I'd much rather have a two-week adventure than have ten 3-day weekends in a row. Fortunately, there's an opportunity to scratch my Black Rock City itch as well. There's a long annual tradition of people visiting the Black Rock Desert at the beginning of July, popularly dubbed the 4th of Juplaya. This is the same location as Burning Man, but rather than creating a temporary city of 70,000 people in a few square miles, small groups of friends set up camps around the fast desert space with no central coordination. I've never been to Juplaya before, since the two-day trip each way always seemed like a big challenge to visit a place I was just going to return to seven weeks later. But with Burning Man off the table, 2021 seems like a great opportunity to explore the unique features "outside the trash fence." Plus, I can throw in a road trip to visit friends and family on the west coast.
As I started planning this trip, I quickly realized that I ought to get an amateur radio (ham) license. Radios are key to Burning Man operations, and with nine years rangering I've come to think of radio chatter as part of the playa experience. But while the org runs a commercial radio system in BRC, the rest of the year requires a ham license to spread your message across the desert.
The U.S. amateur radio system provides three levels of license—technician, general, and amateur extra—each with successively larger parts of the electromagnetic spectrum they're allowed to transmit on. Licenses are gained by passing a multi-choice written exam, with the question pool published in advance. From an academic perspective this seems like an unreliable way to assess someone's full understanding of the subject matter, but on the other hand you don't actually need to know things like how to read a circuit diagram in order to use a push-to-talk radio.
With my road trip starting in mid-June and another short vacation I had planned in early June, I had a pretty limited period of time to learn the material. While waiting for my Technician license manual to arrive, I read through the free PDF The No-Nonsense Technician-Class License Study Guide. After two nights I was able to obtain a passing grade on hamstudy.org, but I sure felt like I didn't understand half of the material. There's a significant focus on the physics of electromagnetism and circuits. I've long felt that my grasp of electromagnetism from Physics II was much worse than my understanding of Newtonian mechanics from Physics I, and probably worse than my understanding of relativity and quantum mechanics from Physics III. I have no problem explaining the dual particle/wave nature of photons and could probably work through probabalistic quantum tunneling, but have been kind of confused for over two decades about what exactly an ampere is.
Once I got the ARRL manual I zipped through the 200 or so pages in four evenings and felt like I had a much better understanding of what the heck was going on. After a few more rounds of hamstudy.org practice exams, I drove to southeast Denver (the license test that best met my time concerns) and managed to get a perfect 35/35 score. That felt like a pretty good accomplishment given that my first exposure to any of the material was only a week earlier. Just for kicks I decided to take the general exam, having studied absolutely none of its questions but having all the radio basics bouncing around my head. I managed a 23/35 on that one, which is three questions shy of a passing grade. I guess the test isn't a completely bogus assessment, then.
By the time I got home an hour and change later, the next callsign on the FCC's stack, KF0FTJ had been assigned to yours truly. I am now legally allowed to transmit on the VHF and UHF bands as well as portions of the HF bands. (The names for portions of the radio spectrum are kind of silly. It feels like someone started with "Low Frequency", "Medium Frequency", and "High Frequency" and then people kept saying "But wait, why not turn it up a notch?" so there's now Very, Ultra, Super, and Extreme High Frequency for [VUSE]HF.)
In general, the lower the frequency the further it can travel, but also the less information can be packed into the signal. Also, the lower the frequency the longer a good antenna needs to be. My main amateur radio interest is in emergency communications and disaster response, for which battery-powered and easily-mobile radios are ideal, so VHF seems to be the primary band. The HF bands allow amateur operators to talk with people hundreds or thousands of miles away, and hams like to geek out on things like bouncing radio waves off the moon and the solar cycle's effect on long-distance communications thanks to the ionosphere. I find that mildly interesting, but I still don't entirely see the attraction in having a complicated radio setup to talk to people on the other side of the continent now that the Internet has made it cheap and easy to talk to any of two or three billion people around the world. I imagine the ham experience was pretty amazing in the '50s through the '80s. Amateur radio experimentation led to many of the Internet protocols that have come to supplant the service.
I think "I have a license, now who will I actually talk to?" is a common issue for hams. Fortunately, the ham community seems to be pretty friendly (they're people who's hobby involves elaborate setups to talk to people, after all). I've been participating in a weekly Boulder Amateur Radio Club discussion net, and yesterday I received a "radiogram" originating in Pasadena congratulating me on getting a new license that was relayed through "Traffic Nets" until someone on the Colorado traffic net picked it up and gave me a phone call to make the delivery. This is way less efficient than email, but I'm glad that folks are keeping in practice with a communication system that can serve as a backup in the face of a widespread Internet outage. Because if there's one thing I've learned working at a major Internet company for a decade it's that having a well-tested plan for component failure is crucial.
I haven’t heard back from you regarding opportunities at Facebook which tells me one of three things:
You’re already employed with 100% satisfaction at Amazon Web Services (AWS), and if that’s the case please let me know so I can stop messaging you.
You’re still interested but haven’t had the time to get back to me. Please use this link to schedule time on my calendar.
You’ve fallen and can’t get up - in that case let me know and I’ll call 911 🚨🚑
Please let me know which one, because I’m starting to worry… Thanks in advance and I look forward to hearing from you.
This actually answers a question I've had for some time: why have 8 Facebook recruiters sent nearly 40 messages over 5 years to an email address that's not on my resume pitching jobs in Seattle, a city that's a thousand miles from where I live? Perhaps the answer is that they think I've been working at Amazon the whole time.
The climate change podcast How to Save a Planet did a recent episode about social movement anthems and why the climate movement is missing one. There was a bunch of great material in the episode, but as someone who grew up around both folk music and social movement awareness, I felt like they missed the mark on a really key feature of a movement anthem. And it got me wound up enough that I wrote a whole long comment to the show about it, reproduced below. I enjoyed the movement song digging that Kendra did around We Shall Overcome and I am excited that you did a show all about finding a good climate anthem. It's much needed!
I think the criteria you laid out are missing a key ingredient: the song needs to be easy to teach to a crowd of people, who can then constructively sing along even if they forget some of the words. A climate anthem needs the key message in an easy-to-remember chorus, and ideally the verses should be easy to sing as call and response. It also needs to work well a capella, or at most with a single guitar. A song with a catchy tune and a danceable beat is probably not a good candidate, because the band won't be at every march. Independent of the lyrics, the clip of All Star by Smash Mouth was the only one played on the show that sounded like it could succeed musically as an anthem.
I also found Dr. Redmond's assessment of the lack of a climate anthem interesting. She proposed that popular culture is tied to Black culture, but the environmental movement has for a long time not been connected to that Black culture. I think that's only part right: it's not the connection to Black popular culture that's missing in much of the environmental movement, but a lack of connection to group singing in general. Singing in church plays a big role in Black communities (and played an even bigger one in the civil rights era). This isn't just a black thing though; socialist groups and labor unions that were predominantly white sang march- and hymn-derived songs like Solidarity Forever at meetings. (Solidarity Forever is, of course, based on an abolitionist hymn and thus connected to the Black struggle for freedom. But it could spread through camps of European immigrants with no connection to African American communities or culture.) With both church and labor union membership way down among left-leaning middle-class white folks, most of us are simply out of practice at singing in groups. And the proliferation of recorded music in the last half century has meant that if we want to hear a song we usually don't need to sing it ourselves.
I was listening to Listening to a podcast featuring Jack's Solar Garden. The idea is to install solar panels on farmland and then grow shade-tolerant crops below it, or let livestock range and benefit from the shade on hot days. This provides the farmer with multiple income streams: electricity sales and agricultural produce. Agroforestry follows a similar farm-as-ecosystem approach—trees, crops, and livestock grown together can be more productive in the long term than the three grown in separate monocultural areas. (This is partly because the three work symbiotically with soil health. Also, chickens are a pretty effective insecticide and fertilizer, reducing cost of inputs.)
This led me to think about maps and statistics I've seen about land use, which tend to account for just a single use for any given acre of land. You might see an infographic about the percentage of land devoted to cattle, to wheat, to forests, to solar power. This accounting system makes the math easier, but blinds the reader to the possibility of multi-use synergy. Why settle for 20 acres of lettuce and 20 acres of solar when you could have 40 acres of both?
As we combat climate change and account for a rapidly-growing global population, the more creative we can get with the mostly-fixed amount of land on the planet the better chance we'll have of thriving as a human species.
I got the first dose of the Pfizer/BioNTech COVID-19 vaccine this afternoon, so I'm pretty psyched about the possibility of having a summer that doesn't revolve around my living room.
The experience of getting the vaccine itself was pretty painless. Walked from my house to a pharmacy, filled out a form, sat around for a few minutes, a purple-haired nurse stuck a small needle into my bicep (way less uncomfortable than a blood draw), and told me to stay nearby for 15 minutes. I walked over to the local game store and picked up the new Dominion set, then walked home.
The experience of actually signing up for a vaccine, on the other hand, is pretty hectic. Since the U.S. health care wasn't really designed and there's no centralization, every vaccine provider has a separate process for signing up for a shot, with different ways of assessing eligibility. I learned last week that a medication I take for psoriatic arthritis qualifies me in Colorado's Phase 1B.4 group, though the state's official website doesn't list which medications meet that criterion, so I had to check with my doctor. I then went to sign up on the King Soopers pharmacy website. They've got a digital assistant that asks a bunch of questions, none of which is "Are you taking a medication that&hellip", so it concluded I wasn't currently eligible. I next tried signing up through BCH (the local hospital, which also owns my primary care doctor's office). Their system emails you when it thinks you qualify, but I discovered that my electronic health record didn't have the relevant drug I'm taking, so the BCH system wouldn't have known I was eligible. (When I went to add the medicine to my profile I also discovered there was at least a dozen ways that this drug is referenced in the database, and I don't know if their eligibility-checking system knows the drug qualifies.) Other websites just listed the eligibility groups and asked which one you were eligible for. Several required you to sign up with an account in their system, and by the time you get through filling out such a form, the appointment slots are likely to be all taken.
Fortunately, enterprising tech-inclined individuals have set up some tools to highlight available vaccination appointments. Vaccine Spotter scrapes and aggregates pharmacy scheduling websites and covaxalerts publishes that info on Twitter. I was able to snag the convenient appointment when I checked Vaccine Spotter shortly after midnight a few days ago, so hooray for being a night owl. (I may have also lucked out that Walgreens wasn't yet on the Colorado website as a provider, so they may have just onboarded and fewer people were obsessively checking their site.)
Coincidentally, we've scheduled our first vacation (not counting a short trip to the family cabin) in over a year for next week, so I'm glad to have an extra layer of defense against potential exposure while soaking in a hot spring. There's light at the end of the tunnel, but keep wearing your mask and stay at distance so we don't blow it before we reach the finish line.
March 2020: "I'm going to the grocery store, I hope I don't get COVID." March 2021: "I'm going to the grocery store, I hope I don't get shot."
Yesterday afternoon a young man from Arvada brought a semi-automatic rifle to the south Boulder King Soopers grocery store and murdered 10 people. Wikipedia has a summary, or a quick search can find a lot of news reports.
I may have spent more time at the Table Mesa Shopping Center (site of the shootings) than any other commercial parcel. My very existence is thanks to my grandparents purchase of a home three blocks away when they retired from the Army. I spent the first month of my life in that house, so this King Soopers might've been the first super market I was ever inside. My grandparents later moved to the Meridian retirement community, the building right behind King Soopers. I spent three years of high school in the building next door to that, when New Vista High School was in the Paddock campus. We would occasionally decide to move class to Café Sole, students would grab lunch at King Soopers or a slice of pizza at Abo's. I spent hundreds of afternoons and weekends at Dragonfire Games playing cards. There was a laser tag arena there for a few years. Laser tag sessions were kind of pricey, so I only played a few times, but I did buy a super-lucky box of Middle-earth starter decks there once. I biked through the King Soopers parking lot to get to class in the morning, and along the edge of it on the way home. I remember buying Otter Pops and Henry Weinhard's Root Beer for D&D games at a friend's office in the Mock Realty building around the corner.
As an adult, I've bought beer at Pettyjohn's Liquor (not to mention the free cardboard boxes for moving). I've eaten breakfast, lunch, or dinner at almost every restaurant there, and it was at Southern Sun that I planned my first Burning Man trip with some old and new friends. That King Soopers was my main grocery store when I moved back to Boulder and lived in Martin Park, and one of my roommates was studying at the cooking school in the shopping center. I've still got clothes that I got when Savers was on the far side and I have clear memories of a couple trips to King Soopers.
Everyone processes a tragedy in their own way. A couple days ago I realized I needed granola, non-dairy Ben & Jerry's, and a few other items. We didn't get it done on Saturday, and Sunday was cold and snowy. Now I've got an odd determination to get to to the 30th Street King Soopers (my current main grocery store), in a completely mundane act of defiance. That's a defiant act for tomorrow, though. Today I had a meeting with Rep. Neguse's environment and climate aide. Then Kelly proposed that it might be nice to step out of the Boulder Bubble for a bit, so we drove down to Denver to buy some games and have a fantastic meal at Domo, which has a fantastically serene traditional Japanese setup. Not feeling like passing back through the membrane quite yet, we stopped at the Target in Superior and overcompensated on the Ben & Jerry's.
There's all kinds of stuff I've wanted to write about in the last year, but man has the will to write been lacking.
There's a bunch of news in the last year that's been a good hook for a letter to the editor, but I never muster the will to poke around for the coverage in a local paper and then write up a response. (I managed to get enough focus this month to collaborate on an LTE about the passing of George Shultz, Republican elder statesman and climate advocate, but we submitted it nearly two weeks after his passing and the paper probably thought it was old news by then.) Last fall I had several ideas about framing carbon fee & dividends for a conservative audience, and had several days that I intended to write something, but have nothing to show for the plans other than my comment contributions to what some other folks wrote.
At the beginning of the year I was planning to be an active voice for bipartisan climate solutions in the new Congress, but then Donald Trump dispatched a mob to defile one of our country's sacred places. Bipartisanship became a challenging hook, and I was too engrossed in the "WTF just happened" details that unfolded on the Internet over the next few weeks. I was sucked in to watching all the videos posted to Parler around the Capitol on January 6th. It was a fascinating slice of history captured by people who probably didn't know just how big a historic moment they were filming. I spent several evenings and weekend days watching them in chronological order, and had thoughts of writing a blog post about what I'd observed, but then I ran out of steam between 3:15 and 3:30 of the day.
Last summer I had a couple design documents I'd said I would write at work and could barely get a couple paragraphs written. I also have several "Update the documentation with new information" bugs assigned to me that I frequently think about but never address. I was able to write a couple good design documents about things I had clear plans on how to build, but I've been nowhere near as prolific in work writing as I was in the 2011 to 2015 time frame.
I've also been pretty lousy at email correspondence during the pandemic (and for the last several years, to be frank), and social video conferences usually feel like a chore.
Oddly enough, despite all this writer's block, I've been significantly more productive at writing code in the last year than I was the previous four. Writing a five paragraph article takes all the energy in the world, but I can knock out code for hours on end with no problem. Writing English as a hobby is a no-go, but I somehow have the focus and clarity to switch from my work chair to my living room chair and still write code for personal projects.
Each December for the past several years, Advent of Code has presented a series of 25 daily programming challenge, with each problem adding to a Christmas-themed narrative. I think I'd seen references to AoC in the past but hadn't paid it any mind. This year, my team at work is evaluating Kotlin for adoption in our Android Java codebase, so a small daily excuse to get experience with the language seemed promising. Plus, there's a global pandemic so it's not like I've got any holiday parties to attend.
The event was more fun than I'd anticipated. Challenges are released at midnight America/New_York each night, and there's a time-to-completion leaderboard, so there's a competitive challenge aspect to get the juices flowing. This wasn't great for health, though—on a couple nights I started programming at 10pm America/Denver while already tired and didn't go to bed until 3am, whether because I was too sleep deprived to effectively debug or because I was having fun giving hints on the contest's subreddit. Mostly it was fun because the problems are small enough to do in one sitting and often involve an interesting algorithm. Lots of participants give themselves an additional challenge, like using a different programming language each day or using an unusual or challenging language—I saw someone posting solutions in the m4 macro language and some folks using Excel. Lots of folks create visualizations of their algorithm solving the problem; this year's challenges involved several which were based on Conway's Game of Life which naturally offer interesting visualizations.
My experience with Kotlin was a bit mixed. Kotlin is a programming language designed to run on the Java Virtual Machine and play well with Java code, but with a more expressive syntax and some features informed by two decades of programming language evolution since Java came into the world. It is perhaps most widely used in the Android ecosystem where some of its features help cover for poor Android framework design and API choices and where its coroutine concurrency model is a better fit for client application programming than Java is. Kotlin can also run in JavaScript and iOS environments, offering a hope of cross-platform shared logic. I've seen enough cross-platform efforts fail to be widely adopted to be skeptical on this front, though.
Using Kotlin for Advent of Code offered several benefits over Java. First, the heavy type inference and lower repetition and boilerplate reduced the number of symbols that had to be typed, which is nice for short programs, particularly one with Fake Internet Points for programming quickly. The standard library provides a lot of handy utilities like ranges, a typed Pair class and check/require (functions which concisely throw an exception if the program is in an invalid state) for which Java needs a library like Guava. when blocks were also handy in many AoC puzzles, and a lot friendlier than a chain of if/else conditions. Kotlin's fluent collection transformations (filter, map, sum, and friends) feel a little more expressive than Java Streams, and I found multiple occasions where "potentially infinite sequences" were helpful. Coroutines (which power sequences) are, I think, Kotlin's biggest selling point, and while most Advent of Code problems don't particularly benefit from concurrency, I found yielding values from a recursive function easier to implement and reason about than accumulating a list that gets returned up the chain.
I'm not entirely won over on Kotlin, though. My first gripe is that the language is at risk of falling into the C++ and Perl trap wherein the language provides multiple ways to do very similar things and two pieces of code which do the same thing look very different. This in turn can create a cognitive impediment when reading code written by a different programmer or team. One example of this is the distinction between properties and no-arg methods. In Kotlin, one writes list.size as a property but list.isEmpty() as a method and I've been unable to find guidance on when to use one rather than the other for read-only state.
Second, one of Kotlin's selling points is nicer handling of nulls, since nullability is part of a type definition (String? is nullable, String is not). This is handy, and reduces boilerplate, particularly with null-happy APIs like Android. But it also means the compiler forces you to handle null cases which you know semantically can't occur, such as calling .max() on a collection that you know is not empty. This leads to a proliferation of method name pairs, one of which throws an exception and one of which returns null (elementAt/elementAtOrNull/elementAtOrDefault, getValue/get/getOrDefault, maxBy/maxByOrNull, maxWith/maxWithOrNull…). This also isn't entirely consistent within the standard library: list[5] throws an exception if the list has fewer than six elements, but map[5] returns null if that key is not present. The need for "OrDefault" method variants also seems a bit odd when the language also provides the Elvis operator (?:) for null-coalescing.
Third, the impression that Kotlin is basically Java with nicer syntax can lead to unpleasant surprises when the Kotlin standard library has a slightly different implementation to a similar method in Java. For example, in Java, String.split with an empty argument returns an array with one character per string: "cake".split("") is the same as new String[] {"c", "a", "k", "e"}. The same behavior holds true in JavaScript, Python, Perl, and perhaps dates back to AWK. Kotlin, on the other hand, returns an array with empty strings at the beginning and end: "cake".split("") is the same as arrayOf("", "c", "a", "k", "e", ""). What's worse, the behavior of splitting on an empty string or pattern is not documented in Kotlin, so I don't know if it's a bug or an intentional choice.
This brings up another of my Kotlin complaints: documentation. There are plenty of valid complaints about Java's verbosity, but the clarity and completeness of Javadoc in the Java world is wonderful. I very rarely have to read the code in the JDK or a widely-used library to understand how it will handle a particular input. (The same cannot be said for Ruby, for example.) Kotlin seems to prefer more terse documentation and rarely gives sample code, so you're often left to figure it out yourself, experimentally. The Kotlin web interface for API documentation also has some notable room for improvement, like proper handling of "Open in new tab" clicks.
My final Kotlin complaint that cropped up during Advent of Code is a sneaky one. One of Kotlin's neat features is extension methods: you can define a method on a type defined by someone else, like operator fun Pair<Int, Int>.plus(other: Pair<Int, Int>) = Pair(first + other.first, second + other.second). This can help the readability of code with several steps by chaining all method calls from top to bottom, whereas Java would end up with a mix of static method calls wrapped around method chains. This feature, however, comes with a major downside: extension methods are resolved statically against the declared type of the receiver. They are not dispatched dynamically, despite having identical syntax as dynamically dispatched methods. A concrete example I ran into: a function which checks the neighboring cells of a 2-D grid used the following code:
fun checkNeighbors(x: Int, y: Int) {
for (i in (x-1..x+1).intersect(0 until height)) {
for (j in (y-1..y+1).intersect(0 until width)) {
// do something with grid[i][j]
}
}
}
This expresses "go through all the cells from above left to below right while staying inside the grid bounds" by using the intersection of pairs of ranges. Unfortunately, this is an O(n^2) algorithm because intersect is defined as an extension method of Iterable, so it runs through all width columns for each height row, even though at most three of each are relevant. I could write a specialized IntRange.intersect(other: IntRange) = IntRange(max(start, other.start), min(endInclusive, other.endInclusive)) extension method, and it would improve the complexity in this code to O(1). But if someone passed an IntRange to a method declared to take an Iterable or a ClosedRange, an intersect call on that argument, the inefficient generic version would be used. This contrasts with Java 8's similar mechanism, default methods on an interface, which allow implementations to provide a specialized version dispatched at runtime.
Returning circularly to the "too many ways to do the same thing" problem, here are some efficient ways to write that grid code in Kotlin:
for (i in (x-1).coerceAtLeast(0)..(x+1).coerceAtMost(height-1)) {
for (j in (y-1).coerceAtLeast(0)..(y+1).coerceAtMost(height-1)) {
for (i in (0 until height).let { (x-1).coerceIn(it)..(x+1).coerceIn(it) }) {
for (j in (0 until width).let { (y-1).coerceIn(it)..(y+1).coerceIn(it) }) {
for (i in x-1..x+1) {
if (i in 0 until height) {
for (j in y-1..y+1) {
if (j in 0 until width) {
for (i in (x-1..x+1).filter((0 until height).contains)) {
for (j in (y-1..y+1).filter((0 until width).contains)) {
but I'm really not sure which is the most idiomatic.
I enjoyed the over-the-top absurdity of this spam message I received through my website. Unsurprisingly, the referenced Bitcoin address has never received a transaction.
Your reputation and business are at stake!
We on your behalf in the message your website address trevorstone.org and your contact information (including in social. Networks and messengers) will send:
+ on 15,897,318 sites, threats with insults to site owners, US residents, Europeans, LGBT and BLM.
+ 790,000 messages to bloggers with threats and insults
+ 2 367 896 public figures and politicians (from the USA and Europe) with threats and insults
+ 70,000 negative reviews about you and your website trevorstone.org
+ 23 467 849 contact forms of sites with threats and insults
+ 150,000 emails messages to people with disabilities with threats and insults, many of them will definitely sue you
+ 57000 emails of messages to veterans with threats and insults, FOR THIS YOU WILL BE EXACTLY SITTED
Following from all of the above, you will get a lot of losses:
+ an abuse from spam house, amazon and many webmasters (for spam, insults and threats) will come to your site trevorstone.org, as a result, your domain will be banned and blacklisted
+ people will sue you because you threatened and humiliated them
+ in court you will not prove anything, everything will look as if you did it all, MOST YOU WILL GO TO PRISON
+ internet will be inundated with negative reviews about you and your website trevorstone.org
+ threats and reprisals from BLM and LGBT community members, in fact, these are dangerous community guys
Total: you will lose your business, all your money, you will spend on lawyers and compensation for court decisions, you will go to jail, your life will turn to hell ...
We already have everything ready to launch all of the above, but we decided to give you a chance to avoid all this, you can buy off a small amount of money.
Make a payment, transfer 0.39 Bitcoins to this address
1JDYfBMP3vg8TcuFuwSHc1Wop3rREqupC4
We are waiting for the transfer from you until November 27, on Saturday November 28, if payment does not come from you, we will begin to destroy your business and you along with it.
This song is called “Alice’s Algorithm” It’s about Alice, and the algorithm But “Alice’s Algorithm” is not the name of the algorithm That’s just the name of the song That’s why I call the song “Alice’s Algorithm”
You can send anything you want with Alice’s algorithm You can send anything you want with Alice’s algorithm Send a syn, you’ll get an ack Two prime numbers are hard to hack You can send anything you want with Alice’s algorithm
Now it all started two Thanksgivings ago, two years ago, on Thanksgiving When my friend and I wanted to send a message to Alice with an algorithm But Alice doesn’t get mail through the algorithm, She gets mail on a server running the algorithm, In the home directory, with her copy of RSA and Carol the sysadmin And livin’ in the home directory like that, they’ve got a lot of room in /var where the spool used to been Havin’ all that room (seein’ as how they deleted all the spools) They decided that they didn’t have to take out their garbage for a long time ( Read more...Collapse )
Context for non-computing folks: computer messaging protocols are often described with Alice, Bob, and Carol sending messages and Eve trying to eavesdrop. There's also a lot of Unix references in there. Context for non-American-folk-music folks: Alice's Restaurant by Arlo Guthrie is one of the greatest satirical songs ever performed. Listen to it first to get the guitar portion rolling around your head while you read these filk lyrics.
Having the GMail address trevorstone@, I get a lot of email destined for other people around the world named Trevor Stone. This misdirected mail can be anything from invoices from contractors to airline ticket confirmations to Uber Eats receipts to messages from family members. But most of it is marketing mail from websites, and most of them seem to be meant for a Trevor Stone from England who is particularly bad at putting typing his correct address.
I noticed an email for this United Kingdom version of Trevor Stone which illustrates an interesting pattern: the internationalization of the consumerism parts of Thanksgiving weekend, even though the "Spend Thursday feasting and visiting with your family" part seems to remain an American-only tradition.
Date: Thursday 26 Nov 2020 15:38:28 +0000 From: Millwall FC Subject: An early Black Friday offer has been spotted!
Enjoy an early Black Friday offer - get free postage and packaging (UK ONLY) when you spend £60 or more, using the code below...
This UK-only Black Friday special has an extra dose of irony because the Millwall FC's mascot is The Lions, but they're not the Lions football team most associated with Thanksgiving football.
Today, November 3rd, 2020, is Election Day. It is one of the sacred days of the American calendar, when the people choose our next set of leaders. It is the day we begin to learn what our fellow citizens think, and whether enough of them think like us that our favored candidate will take the reins next year.
With 21st Century media and social science we already know a lot about what our fellow citizens think. We know that about 45% of Americans approve of Donald Trump’s performance and a little more than half of Americans disapprove. We know that in almost every presidential race without a major third-party candidate, at least 40% of voters cast their ballot for the losing candidate. Both Democratic and Republican candidates have received donations from millions of Americans, and all told around $14 billion has been spent to influence the election, nearly $100 per voter. All of which is to say that, regardless of who wins, tens of millions of Americans will have voted for someone else. And while we often talk about red states and blue states, very few states are forecast to cast less than one third of ballots for either Biden or Trump. No matter where you live, you’re probably not too far from a pocket of support for a different party.
Over the past several decades, American political partisanship has increased dramatically. With the ease of moving, we’ve geographically clustered ourselves into areas of partisanship—your neighbors today are more likely to share your political views than neighbors fifty years ago. This also means most Congressional races are decided in the primaries more so than in the general election, leading to an increasingly polarized congress. With an abundance of media choices, Americans can choose to get their news from publishers whose partisan lean matches their own—and publishers can tailor their news to match the partisan lean of their target demographic. This has led to a country in which the same event has wildly different interpretations on the left and the right (even within mainstream partisan groups), and in which there’s often disagreement about basic facts, depending on media diet. This is good business for media companies, producing a loyal audience and reliable advertising, but it’s bad for democracy.
This intense partisanship has led to a country in which people have a very distorted view of the people on “the other side.” Fear and outrage are more effective tools than nuance and curiosity for attracting media eyeballs and motivating campaign contributions, so our partisan information sources send us a steady diet of stories about all the bad ideas and negative personality traits of politicians from the other side of the aisle. Depending on your social and media world you might think that Democrats are out to destroy America… or that Republicans are trying to do it. This partisan animus then naturally extends to either party’s voters. Some folks on the right view any vote for Joe Biden as support for socialism (despite his primary defeat of the socialist candidate) while folks on the left have turned “Trump supporter” into shorthand for a violent, racist, anti-intellectual stereotype (despite Trump’s 2016 performance of 20% of votes from people of color and 40% of college graduates). The result is a sort of negative partisanship: people often vote against candidates, parties, and perceived ideologies rather than voting because they’re inspired by positive traits. We may not love the person we’re voting for, but at least he’s not like that other guy, and we’ll keep those terrible people out of power.
Is it possible that nearly half of all Americans are stupid, evil, or want to destroy America? No. If a person says or does something that doesn’t make sense to you, there’s a good chance they’re just operating with a different internal logic and a worldview than yours. When we let members of our own partisan tribe tell us about members of the other tribe, to define them by negative characteristics and differences from our tribe, it’s known as “othering,” a form of discrimination. And with the geographic and demographic partisan alignment over the last 40 years, this political othering builds on othering based on race, education, and the urban/rural divide. Left unchecked, othering and discrimination tends to escalate, which is dangerous ina democracy. We’ve learned that one of the most important ways to address othering is to let people tell their own story, to share their own experience. One of the most radical things you can do in the time of hyperpartisanship is to listen to people on “the other side.”
Humans live complex lives, and there are many factors that can lead to electoral support. Our moral values are expressed in different ways, with some people resonating more with candidates who display values of care or fairness, others resonating with loyalty or purity. Some voters resonate with candidate personalities. Some voters decide based on policy support. Some vote based on party loyalty, or are influenced by leaders in their own identity groups. Any successful presidential campaign represents an alliance of voters who made up their mind in different ways. Some voters resonate with candidates in both parties, or are torn between the policies of one candidate and the personal character of another. Some don’t find a home in either major party, and are coaxed into voting for the lesser perceived evil[1]. When we reduce all of a candidate’s voters to a single mental category we miss the opportunity to understand the rich viewpoints and experiences that came together for this moment in electoral time. Some of the “other team’s” voters differ from us in many measures, but we might find a lot in common with other voters: they share many of our values, they share our group identities, but there was that one thing that led them to check box A instead of B. But we won’t find that connection if we approach them from a place of prejudgment and if we don’t listen when they tell their story.
Even in highly partisan places and in organizations with a significant ideological lean, a significant number of people vote for the party that’s not locally dominant. Donald Trump got around 10% of the vote in famously Democratic cities like San Francisco, Boston, and Baltimore while Hillary Clinton captured 10 to 20% of the vote in most small rural counties. So even if your town, your company, or your religious community feel like places where everyone agrees on politics, they’re probably not. But it’s likely that folks with the minority position try to keep a low profile: they voted based on their values, but if they speak up about it they risk being othered, excluded, or harassed, all of which make us feel horrible.
There’s a lot at stake in today’s election, and emotions are running high. Folks who voted for winning candidates might feel elated or relieved. Folks whose candidate didn’t make the bar might feel shock, despair, anger, or fear. As the vote is counted this week we need to be aware that our colleagues and neighbors may feel very differently than we do. And what we say about their candidate or their political party may feel like an attack on their tribe or on them personally. So please be considerate as the democratic process evolves. Empathize with your colleagues. Listen to your neighbors. Respect that they made a reasonable decision, based on their own values and priorities. Recognize that we’re all in this together: democracy depends on people’s ability to collaborate despite disagreements. And above all, be excellent to each other.
[1] Duverger’s law finds that an electoral system like America’s tends to produce a two-party system with limited choices.
I welcome comments on this piece. I regret that it is but a first draft, yet its value would be reduced if I waited a week to share a more perfect version. Thank you for reading, and take care of yourself.
It's late October, so I just did almost all my live TV watching for the year, between postseason baseball and presidential debates. And since my brain wouldn't shut up about this for over 3 hours, here's some interesting stats from the last 20 World Series, 2001–2020. (If you want to nerd out over more, Wikipedia of course has a list of all the Series.)
National League teams won 11 times, American League teams won 9.
No team won back-to-back World Series, and only four teams had back-to-back league pennants (two losing twice, two going 1–1).
The Red Sox won 4, Giants won 3, Cardinals won 2, and 11 different teams won 1. Six teams lost twice. It's also the first 20-year period in which the Yankees only won one World Series since the first 20 year window (Yankees first win was 1923).
Red Sox–Cardinals was the only repeat matchup. (The previous 20 series also had a single repeat, Yankees–Braves. The previous 20 featured three between the Yankees and Dodgers and two Orioles–Pirates Series. The 20 before that, the Yankees faced the Dodgers 7 times and the Giants, Braves, and Cardinals twice each.)
Several teams won their first World Series in franchise history or their first Series after a 30+ year drought: Chicago Cubs after 108 years, Chicago White Sox after 88 years, Boston Red Sox after 86 years, San Francisco Giants after 56 years (first since move from New York), Dodgers after 32 years, Royals after 30 years; Houston Astros in their 56th year, Los Angeles Angels in their 42nd year, Arizona Diamondbacks in their 4th year. Additionally, the Philadelphia Phillies became the final of the original 16 MLB franchises to win a second World Series.
20 teams made at least one appearance. Every expansion team made an appearance except four: the Mariners, Brewers, Blue Jays, and Padres. This period contained the first World Series appearance by the Angels, Astros, Diamondbacks, Nationals, Rays, and Rockies.
Of original 16 MLB franchises, only six didn't appear at least once in the last 20 Series: Athletics, Braves, Orioles, Pirates, Reds, Twins.
Seven Series went 7 games, four went 6 games, five went 5 games, four were swept in 4 games. The Nationals became the first team to win all four road games and lose all three home games. In four championships, the Red Sox lost a total of three games.
10 of the 40 pennants in this period were won by a wild card team; 6 wild card teams won the Series, and two World Series featured two wild card teams. I suspect the wild card expansion (now four teams per league are in the playoffs) have contributed to the recent diversity in appearances and victories: a team that's performing really well late in the year now has more chances to beat an established team that got a big division lead early but didn't finish as strong.
An endless fiesta would be exhausting and demoralizing: the pleasure would go out of it, the masks would disguise only fatigue and apathy, and there would eventually be nothing to celebrate. The ordinary and the extraordinary need each other, or rather everyday life needs to be interrupted from time to time—which is not to say that we need disaster, only that it sometimes supplies the interruption in which the other work of society is done. Carnival and revolution are likewise interruptions of everyday life, but their point is to provide something that allows you to return to that life with more power, more solidarity, more hope. -- Rebecca Solnit, Paradise Built in Hell
At temporary events like Burning Man and Dragonfest I've often heard someone say something like "We should create a community where we do this year round." This quote refutes the idea much more eloquently than I have.
The relationship between disaster and revolution has seldom been explored, though it crops up throughout the history of revolutions. Catastrophic weather across France in the summer of 1788 brought on the crop failures and bad harvests that led to the rising bread prices, shortages, and hunger that played a major role in triggering the French Revolution the following year. The 1870–71 siege and occupation of Paris in the Franco-Prussian War brought on the sense of daring and solidarity that made possible the Paris Commune—several weeks of insurrectionary self-government Kropotkin and anarchists everywhere have cherished ever since. Belli spoke of Nicaraguans feeling after the earthquake that since they could lose their life, they wanted to make it means something, even if that involved risks. Disaster and crisis can stiffen resolve… Sometimes they work by making a bad situation worse to the point of intolerability; they create a breaking point. Sometimes they do so by making obvious an injustice or agenda that was opaque before. Sometimes they do so by generating the circumstances in which people discover each other and thereby a sense of civil society and collective power. But there is no formula; there are no certainties. Leftists of a certain era liked to believe that the intensification of suffering produced revolution and was therefore to be desired or even encouraged; no such reliable formula ties social change to disaster or other suffering; calamities are at best openings through which a people may take power—or may lose the contest and be further subjugated.
— Rebecca Solnit, A Paradise Built in Hell: the extraordinary communities that arise in disaster
Although I've been making slow progress (distracted by 2020!), A Paradise Built in Hell was an excellent book choice for 2020.
I've also been listening to Mike Duncan's Revolutions podcast for the last several years, too[1]. I've noticed a theme that what history knows as the big moments that made a revolution seem inevitable were often a surprise or a minor event at the time. When the social order sits atop a rotten and rickety structure, it's anyone's guess what will happen when a piece of that edifice gives way.
[1] The series will end after the 1917 Russian revolution and it's currently taking a break after the 1905 Russian revolution, so if you start binging now, the last episode should be available by the time you're ready to listen.
I realized today that the entire premise of one of the greatest Rock & Roll songs in history has been obsoleted by the 21st Century.
Long distance information, give me Memphis, Tennessee Help me find the party trying to get in touch with me She could not leave her number, but I know who placed the call Because my uncle took the message and he wrote it on the wall
The geography is also a little questionable these days.
Help me, information, get in touch with my Marie She's the only one who'd phone me here from Memphis, Tennessee Her home is on the south side, high up on a ridge Just a half a mile from the Mississippi Bridge
I did, however, finally realize what the relationship between Marie and the singer is.
Help me, information, more than that I cannot add Only that I miss her and all the fun we had But we were pulled apart because her mom did not agree And tore apart our happy home in Memphis Tennessee
Last time I saw Marie she's waving me goodbye With hurry home drops on her cheek that trickled from her eye Marie is only six years old, information please Try to put me through to her in Memphis Tennessee
Given Chuck Berry's reputation for interest in teenage girls (he was convicted of having sex with a 14-year-old after transporting her across state lines, though he appealed claiming prejudice), I'd always assumed that Marie was a love interest, but 6-years-old seemed disconcertingly wrong. But the song makes way more sense if the singer had a relationship with Marie's mother and developed a fondness for her daughter (either as the father or as the boyfriend of a single mother), but then got kicked out by the mother.