Trevor Stone Character

Sticky Post: Flwyd has Moved to Dreamwidth

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.

While all good things will come to an end, this blog has several years to go in its new home. Subscribe to my journal on Dreamwidth or with your favorite RSS reader. You can also find me on my website, Twitter, and Google+. Keep sharing!
Trevor baby stare

Advent of Kotlin

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.

This entry was originally posted at https://flwyd.dreamwidth.org/396527.html – comment over there.

spam lite

Spam: Precise counts of threats and insults

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 entry was originally posted at https://flwyd.dreamwidth.org/396038.html – comment over there.

  • Current Music
    KGNU - Musica Mundi
  • Tags
Trevor baby stare

Alice's Algorithm

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
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.

This entry was originally posted at https://flwyd.dreamwidth.org/395777.html – comment over there.

spam lite

Exporting American Traditions of Consumerism

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.

This entry was originally posted at https://flwyd.dreamwidth.org/395658.html – comment over there.

Trevor baby stare

On Partisanship and Othering

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.

This entry was originally posted at https://flwyd.dreamwidth.org/395373.html – comment over there.

Trevor baby stare

20 Years of World Series Stats

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.

This entry was originally posted at https://flwyd.dreamwidth.org/395227.html – comment over there.

Trevor baby stare

Don't Vote for the Endless Party

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.

This entry was originally posted at https://flwyd.dreamwidth.org/394867.html – comment over there.