Re-Evaluating Kotlin

Published at 15:40 on 15 December 2025

Back in 2019, I wrote:

The pity is that once one does things other than Android software development in Kotlin, the rough edges in its ecosystem quickly become all too apparent. Just out of curiosity I’ve been playing with the Ktor server-side framework. The documentation ranges from flat-out obsolete (and thus incorrect) to simply nonexistent. The result is that even simple things take hours of tedious experimentation to determine how to do.

I’m hoping that Android development goes better, but unless those rough edges get smoothed out, and soon, Kotlin may well end up being stereotyped as an Android-only thing.

Only last month, I wrote:

The big problem with Java is not the language, it is the culture around the language. I have a friend with a number of pet sayings, one of which is “tradition is mightier than innovation,” and that certainly applies in spades to Java. There’s just so much bad tradition enshrined as respected convention in the Java world. I call the result Java Community Antipatterns or JCA’s for short.

      ⋮

If it weren’t for the JCA’s, Kotlin would be a near-ideal programming language. If it weren’t for the heat and dryness, Phoenix would have a near-ideal climate. (And aside from that, Mrs. Lincoln, how did you enjoy the play?)

But, I ended up concluding:

The Java community’s faults may be legion, but Java set out to be a “write once, run anywhere” language, and its virtual machine has to this date succeeded at that goal better than any other such environment of which I am aware.

So I’m back to coding in Kotlin, and once again Kotlin’s nemesis becomes clear. It is its proximity to the Java universe, and by implication the universe of JCA’s.

The Java virtual machine’s advantages make the concept of a language like Kotlin tempting. It is why JetBrains decided to create Kotlin. It is why I have been coding in Kotlin.

Unfortunately, realizing that concept is a very tall order. Quite simply, it is not exactly easy to take a complicated, badly-designed, antiquated ecosystem and attempt to layer a more rational, more modern, more well-designed one on top of it. This problem becomes all the more acute if said ecosystem is associated with a culture that has enshrined harmful antipatterns as part of its respected traditions. The Kotlin development team is obviously trying as hard as they can, but it doesn’t matter: their effort still falls short.

I am picking up a project I put aside about five months ago, due to a need then to focus on other more pressing goals. Then, I had foundered for some time on serialization. Kotlin has what is in theory a great serialization subsystem. Of course, given the Java world it was layered on, it took no small effort to implement it. And the latest version of Kotlin at the time hadn’t quite got its implementation right; I was getting bitten by those bugs, which were causing my code to throw exceptions and die. JetBrains was aware of those issues, and planning to fix them in the future, but that didn’t help me in the here and now. Eventually, after blowing several days on the issue, I found the magic combination of an older Kotlin compiler and serialization library that did not make these bugs manifest.

That resolved my issue, but enough time had transpired that when I recently resumed my efforts, one of the things at the top of my agenda was to upgrade to the current versions of things and see if JetBrains had fixed the bugs. I did, and they had. So far, so good.

The problem is, the build system (based on the Java universe’s Gradle, which coming from the Java world is the standard shambolic mess you find in that world) has now for some reason started producing a corrupt Jar file. The jar command-line utility can list and process the Jar file. It can locate the class I am trying to invoke. Yet when I attempt to invoke it, the JVM claims it cannot find the class.

So now I have to troubleshoot that build system and figure out why it is (once again) failing me. And this is the sort of shit that keeps coming up in the Kotlin world, simply due to its proximity to the Java one.

Where this goes, I am not sure. Maybe I will find a resolution or a workaround, like I did the last time the build system started spitting out Jar files that were corrupted in a slightly different way. Maybe not. Maybe I will just give up on Kotlin, despite its advantages, because the disadvantages simply outweigh them.

A Blue Wave? Maybe Not

Published at 08:56 on 14 December 2025

Yes, I know that Trump is not exactly doing too hot in the polls right now. Political strategist Rick Wilson is positively giddy about it.

I have argued recently that a blue wave or two is likely to be significantly less consequential, in the long run, than many people think. Now I wish to argue that the hypothetical blue wave might not happen at all.

The reason is simple: war. Americans are, on the whole, an astonishingly ignorant people when it comes to foreign policy. This ignorance is no accident; Establishment politics has carefully tended and nurtured it for many decades. All the better to help prevent democratic accountability from interfering with military adventurism. It is one of the natural consequences of being a superpower, and a key reason why superpower status is a threat to free society.

Any administration that starts a war historically gets an incredible amount of deferential treatment from the mainstream media, the purported opposition party (both parties are united in their support for empire), and the populace as a whole. Do not think for a minute that this cannot apply to a war against Venezuela.

Maybe it won’t. We’re not that far past getting burned by the consequences of past deferential treatment for wars in Iraq and Afghanistan. Maybe this one will come too soon on the heels of the earlier ones.

But don’t be too sure about that. It is at least as plausible that Trump will succeed in selling his Venezuela war. The authoritarian regime that runs Venezuela is not precisely the sort of government to inspire sympathy. Advocates of war will be able to paint opponents of war as Maduro allies or sympathizers, a characterization made all the easier by the shameful reality that it is not very hard to find American leftists that are allies or sympathizers of the Maduro regime. The Establishment media, already in many cases cravenly capitulating to Trump, could very easily once more assume its historic role as propagandists for the ruling class’ latest war of choice.

If this happens, Trump could easily prevail in the next few electoral cycles. I am quite sure, in fact, that this is a huge part of why Trump seems eager for a war with Venezuela. I will give the man credit for one thing: he knows advanced state of moral decline of the nation he leads better than virtually anyone else in the halls of power, and he has used this knowledge to become what is already one of the most successful, effective, and consequential presidents in U.S. history.

Yes, successful and effective. He has made more change, more quickly, than any president since FDR and quite possibly any since Lincoln. It is now part of established political precedent that U.S. presidents may incite coups to attempt to stay in power, can lie about just about anything, can make law and policy by fiat with little or no input from Congress, engage in crass nepotism, receive bribes, and cannot and should not be held accountable under the law.

To assume that a war in Venezuela will fail to keep Trump in power is to assume a moral and informed American public that, by and large, simply does not exist. See Rule No. 3.

Finally

Published at 08:37 on 12 December 2025

One of the things that has been worrying me most about Canadian politics is the smug sense of complacency. There is just too much belief in the concept that being a separate country will somehow be a free ticket to escape many consequences of the ongoing transition to fascism south of the border.

In particular, I have been worried about the complacency on national defence. On the Left, I saw complacency about the mere need for defence. This is understandable, as military spending has often been sold under the guise of “defence” when in fact actual defence has little or nothing to do with it. On the Right, there is not so much problem with the very concept of defence, but there is a reluctance to see the USA having become the sort of threat it has actually become. This is also understandable, as acknowledging so means acknowledging no small amount of dirty laundry in the Right’s very own hamper.

That is why I find this to be extremely welcome news. Apparently the Canadian military has been quietly doing an honest assessment of the situation, and come to the obvious conclusion: that the cause of peace and freedom for Canada is now best served by pursuing a measure of military deterrence.

Better yet are the voices on the Left, such as Charlie Angus, who have traditionally been quite skeptical of military spending. Not so much any more, perhaps. Let’s hope so.

Armed struggle is indeed a highly unpleasant thing, but ultimately the world is complex and messy place that does not lend itself to any one simplistic rule (such as “war bad”). As John Stuart Mill once observed:

War is an ugly thing, but not the ugliest of things: the decayed and degraded state of moral and patriotic feeling which thinks that nothing is worth a war, is much worse. When a people are used as mere human instruments for firing cannon or thrusting bayonets, in the service and for the selfish purposes of a master, such war degrades a people. A war to protect other human beings against tyrannical injustice; a war to give victory to their own ideas of right and good, and which is their own war, carried on for an honest purpose by their free choice, — is often the means of their regeneration. A man who has nothing which he is willing to fight for, nothing which he cares more about than he does about his personal safety, is a miserable creature who has no chance of being free, unless made and kept so by the exertions of better men than himself. As long as justice and injustice have not terminated their ever-renewing fight for ascendancy in the affairs of mankind, human beings must be willing, when need is, to do battle for the one against the other.

But it doesn’t have to be so dramatic as that. As the old saying goes, Si vis pacem, para bellum. The best possible use of a fighting force is the use that does not involve any actual fighting; the mere presence of such a force can serve to detract a would-be evildoer and aggressor, by underscoring that the costs of evildoing and aggression are unlikely to be cheap.

And yes, this can work against a significantly more powerful opponent. First, you have the asymmetry of sacrifice: a people are generally willing to sacrifice more to preserve their own freedom than they are to subjugate someone else’s. Then, you have the asymmetry of mission: in order to succeed at conquering a country, the conquerer has to achieve complete control over the conquered. In order to succeed at resisting a conqueror, one needs to do far less; one needs merely to deny the conqueror that control.

Make it clear to Trump that a forcible annexation will be more trouble than it is worth, and Trump will likely forget about the idea (or at least repeatedly postpone it, which accomplishes the same thing). Appealing to a fascist’s sense of justice and humanity is both pointless and foolish, as fascists are lacking in both. Appealing to a fascist’s sense of what is best for his personal power and prestige, however, offers a very real chance of being a successful appeal. And this is not merely theoretical; Finland for many years pursued such policies with respect to the red fascism just to its east, and thereby preserved its independence.

If Canada makes it clear to American fascism that the cause of American fascism is best served by seeking some form of coexistence with a democratic Canada, coexistence it is likely to be, which is far better than being a fascist vassal state.

Revolution, Not Reform

Published at 10:09 on 2 December 2025

I really don’t think there can honestly be debate on these two options any more, not in the context of U.S. politics.

This is for the simple fact that this particular ship has already sailed. It is abundantly clear that the U.S. is already in the midst of a fascist revolution of sorts. The signs of revolutionary change are all over the place:

  • Imposing tariffs by fiat.
  • Courts, particularly the Supreme Court in its decision that presidents have basically unlimited authority, endorsing a dictatorial presidency.
  • Demolishing the East Wing of the White House with no public approval process and no advance notice, for the purpose of clearing the way for a giant ballroom funded by bribe money.
  • DOGE making massive, extra-legal changes to the Federal bureaucracy.
  • Denying the clear results of the 2020 election, and pardoning those involved in his coup attempt.
  • Politically-motivated pardons of corrupt officials.
  • ICE —
    • Extrajudicial detentions and deportations.
    • Ignoring court orders.
    • Masked secret agents.
    • Routine brutality.
    • Denying Representatives and Senators access and oversight.
    • Massive funding for more of the same (and worse) approved.
  • Politically-motivated retribution against law firms, universities, and news media who act contrary the regime’s wishes.
  • The capitalist class mostly falling in line behind the regime.
  • Extrajudicial killings on the high seas.
  • Refusing to spend duly-appropriated funds.
  • Spending funds without proper appropriation.
  • Purging military officials judged likely to be insufficiently subservient to the president and any unlawful orders he might issue.

Even many centre-right sources such are now saying it, or seriously implying it: Joe Walsh, Peter Wehner, and The Bulwark to name just three examples.

Yet, despite this, the fascists have not achieved total power. I recently moved this site out of the U.S.A., yes, but that move was anticipatory. There’s plenty of anti-regime material openly circulating in the U.S.A. This would not be the case in a totalitarian society.

It is also clear that Trump is not very popular. That’s just one poll, of course, but it’s a reliable one that has been conducted for decades, and other polls are saying the same thing. Plus you have the electoral backlash at the start of this month, which indicates that the signs in the polls are not just phantoms (and again, that such a backlash can occur is a sign the regime lacks total control).

Where this all goes is unclear. There have been some signs of an independent resistance, but the overall level of it has been nowhere near enough to force the needed changes.

It really seems that most opposed to Trump are pinning their hopes on a big blue wave in 2026 and again in 2028. Even if one is generous and assumes such waves come, an honest assessment will I believe conclude that it is highly unlikely to accomplish that much. This is, after all, the Democratic Party we are talking about (see Rule No. 2). It didn’t accomplish all that much the last time; the Biden years proved to be just a momentary pause in an overall march to fascism. Why should it prove any different the next time?

Yes, there are younger Democrats like A.O.C. who wish to do more, but the party as a whole is still firmly in the hands of an old guard that has proven itself to be more of a willing co-participant than an oppositional force when it comes to the ongoing transition to fascism. A massive none of the above opposition movement could force the Democrats’ hand in a useful way, but again, such a thing does not currently exist.

Until something changes, then, my general prognosis remains pessimistic.

The Trump/Mamdani “Surprise”

Published at 07:55 on 22 November 2025

Not sure how much of a surprise it was, though I expected them to be each others’ foils, too.

Perhaps Trump senses picking fights with Mamdani would be a losing game for him.

Perhaps Mamdani’s charisma won out. The guy is a natural-born politician: absolutely great at making people like him. It’s one of the reasons he won.

But, again, I am not sure just how much of a surprise this really is. That is because, despite all the rhetoric about the two being polar opposites, they are less so than many realize. Yes, they are on opposite ends of the left/right political spectrum, but that is only one way of classifying politicians.

They are both outsiders, disliked by their party’s established elites (though this is no longer the case for Trump, given that he now is one of his party’s established elites, it once was the case). They both appeal to some of the same crowds (in the wake of Mamdani’s surprise primary victory, polls indicated no small amount of Trump/Mamdani voters). They both play the populist game. They both are New Yorkers.

Yes, there are important differences despite all that. I am not saying they are two peas in a pod. I am just saying they are not the absolute diametric opposites they are often portrayed to be.

And this is the big problem with the whole “Trump is far right, and his victory shows the Democrats need to move to the right in response to the verdict of the recent election” line. Voters are not pundits, and do not think about politics like pundits do. It’s one of the things Rachael Bitecofer (not leftist by any means) harps on.

And yes, arguably this means that many voters are stunningly ignorant and misinformed. Cry harder. There is the electorate you might wish the USA had, and the one it actually has, and they are two distinct and different things. To paraphrase a famous ex-Secretary of Defense, elections are fought with the electorate we actually have, not the electorate we might wish to have. See also Rule No. 3.

Finally, this is how things stand with Trump and Mamdani right now. Wait a week (or even a day) and they might be quite different. This is Trump we are talking about, and Trump is famously unpredictable. They may well still turn out to be each others’ foils.

On Boredom

Published at 08:28 on 21 November 2025

Going on an Internet social media diet has meant once again occasionally being bored. There is no longer the default activity of getting distracted by whatever (intentionally selected to be distracting) stuff a timeline shoves my way.

We are taught to dislike boredom, and to avoid it. I think this is a mistake. Boredom is a natural outcome of being faced with no obvious thing to do. It means being compelled to step back, think about one’s life and one’s priorities, and decide on something new to do. (And usually, it’s easy enough: upon thought, there are always a large number of things I want or need to do that can be done.)

Boredom lets me thoughtfully decide what my life priorities are, not some large, unaccountable social media business with extremely dubious morals. Sure, it means having to do a little (mental) work, but shirking necessary work is not a virtue; it is the vice of laziness.

A little boredom is a good thing.

Cutover Complete

Published at 13:17 on 19 November 2025

If you can read this, it means the site cutover is (hopefully) complete. This site is now being hosted by a server in Canada, in a server farm being run by a non-US (French) entity.

The DNS name service (for you non-geeks, that is what makes the blackcap.name part of this site’s address work) has yet to be cut over, but that is because there is about a year left on my existing contact, and I am being cheap. I already have an existing business relationship with a Canadian name registry, and if things start going south rapidly it won’t be terribly hard to cut that over.

Given the current state of affairs, I think it best remove as many dependencies on US-based organizations as possible. This is not exactly a prominent blog, but still better safe than sorry. With authoritarian bastards, you never know.

Portable GUI Framework Principles

Published at 08:25 on 17 November 2025

There are two major schools of thought when it comes to portable graphical user interface frameworks:

  1. To create applications that harmonize as well as possible with the rest of the platform an application happens to be running on.
  2. To create applications that appear as alike as possible, no matter what platform an application happens to be running on.

It is my contention that, for desktop applications, the first principle is the correct one, and the second principle is a harmful design anti-pattern.

The reason is quite simple: most users use one sort of platform, and that is it. You have Windows users, Mac users, and Linux users, and those users tend to stick with their desktop platform of choice. So they don’t care how a given application looks on some other platform. All they care about is how well it harmonizes with the rest of the platform they do use. This makes the basic rules of the game the same no matter what application they happen to be using. I don’t care how special you think your own application is, so far as the average user is concerned, it’s just another tool in their toolbox.

And it is the users, not the developer, who is the truly important ones here. The users are the ones for whom the application was written, after all. They vastly outnumber the developers.

Yes, some users switch between platforms of different types. That is their choice. As part of their choice, they have accepted the natural consequence of having to deal with multiple pattern languages. There is no way to be such a user and to not have this consequence imposed on one. As such, an application whose look and feel varies from platform to platform does not impose any significant new onerous cost on such users.

I am speaking here about desktop applications. For smartphone applications, the matter is quite different. This is because, despite all the hullabaloo about which is best, the Android look and feel really does not differ that much from the iPhone look and feel. It is one of the things that really struck me when I moved from Android to iPhone. Yes, there were a few places where I got confused and had to get used to doing things “the iPhone way,” but surprisingly few. For the most part, I was able to just pick up my new iPhone and start using it.

Since the pattern languages of the two smartphone platforms are so similar, it is sensible to have a goal of a smartphone app appearing as alike as possible on both platforms. It makes the jobs of your documentation writers and user-support people easier, and it does so at approximately zero cost to any end user.

It is even less appropriate to have a goal of making a smartphone app and a desktop application appear as identical as possible than it is to have such a goal for two different desktop platforms. This is because the two basic types of platform are so radically different. A smartphone is profoundly resource-deprived compared to a desktop system. The desktop can be an appropriate place to host large, complex applications (assuming large, complex things need to be done). A smartphone is never an appropriate place for such an application.

What this all means is that frameworks like Avalonia which prioritize Principle No. 2 above should be seen as primarily smartphone frameworks that also happen to support the desktop… badly.

Alternatives to the JVM for Portable Desktop Applications

Published at 19:17 on 16 November 2025

I have been using the JVM (Java Virtual Machine) to host desktop applications I develop. Originally I wrote the code in Java, but in recent years have switched to Kotlin, because it is a more modern language with a more concise and expressive syntax and a more sensibly-designed standard library.

The big problem with Java is not the language, it is the culture around the language. I have a friend with a number of pet sayings, one of which is “tradition is mightier than innovation,” and that certainly applies in spades to Java. There’s just so much bad tradition enshrined as respected convention in the Java world. I call the result Java Community Antipatterns or JCA’s for short.

Kotlin is better in the JCA department, but due to its intellectual proximity to the Java world, some of the Java brain rot has inevitably bled over, so Kotlin still has its issues. To pick just two examples:

  • Its Ktor Client HTTP request library is a lot more complex than it ought to be (way more complex than the Requests library that is common in the Python world or the standard System.Net.Http package of the .NET world). Despite the complexity, some of its features, such as bearer token management, still manage to fall short of what is commonly needed.
  • Its lightweight multithreading is likewise (there are both Job and Deferred objects, both very similar yet subtly different, where .NET gets along just fine with a single Task object).

On top of that, for a lot of things, there simply isn’t a Kotlin library. You end up calling a Java library. That is easy enough to do, because Kotlin runs on the JVM and was designed to interoperate with Java code, but the Java library is inevitably a lot clunkier and harder to use than it ought to be, due to those JCA’s.

If it weren’t for the JCA’s, Kotlin would be a near-ideal programming language. If it weren’t for the heat and dryness, Phoenix would have a near-ideal climate. (And aside from that, Mrs. Lincoln, how did you enjoy the play?)

So I decided to kick the tires on potential alternatives yet again. Always a good idea, because the state of the art is always in flux in the computing world. And the answer I got was: despite the flaws of the JVM, it’s still hard to do better than it.

Mostly, it boils down to three things the Java world got right:

  • To prioritize platform agnosticism.
  • To include graphical user interface (GUI) capability in the core framework.
  • To prioritize, or at least facilitate, making the graphical elements in Java GUI programs harmonize with the overall pattern language of the platform the application happens to be executing on.

The first two encapsulate the “write once, run anywhere” philosophy that has been one of Java’s key design principles basically since Day One. Other virtual machines still just don’t do as good a job of actualizing this principle.

This most often manifests when graphical desktop applications are involved. Pretty much any virtual machine out there will do a great job of running command line utilities or daemons running as detached jobs portably.

Python, for example, has a great cross-platform GUI library called PyQt. Alas, it doesn’t ship with it; one must add it on. And, like many Python libraries, it isn’t written purely in Python. In fact, it’s mostly written in C++, a language that compiles down to machine code, not portable byte code. This makes it a lot harder to distribute a run-anywhere application, particularly on platforms like the Mac, which is unusually programmer-hostile in this regard.

Microsoft .NET has a very nice virtual machine, with a standard library that, unlike Java’s, is for the most part well-designed and easy to use. But it was written by Microsoft, whose corporate interests as the creator of Windows run counter to the ideal of platform agnosticism. .NET code can run (and long has been able to run) on Macs and Linux boxes… as long as you stick to command-line or daemon programs. Out-of-the-box desktop support is no longer strictly limited to Windows (Macs are now supported), but Linux is left out in the cold even as of this late date.

There are third-party frameworks like Avalonia that claim to address this deficiency, but by not being present out-of-the-box, they raise the same gotchas that PyQt does in Python. Plus most of them fail badly when it comes to harmonizing well with the overall pattern language of a platform.

What it all boils down to is that I could shift to some alternate platform, and this would make my life easier in some respects, but only at the cost of making it significantly harder in others, or inescapably compromising the quality of my applications. It is far from clear to me that there would be any overall net benefit. In fact, I rather suspect the opposite would be the case. I guess that’s good news in a sense, as it means I probably haven’t been wasting my time using a suboptimal platform.

The Java community’s faults may be legion, but Java set out to be a “write once, run anywhere” language, and its virtual machine has to this date succeeded at that goal better than any other such environment of which I am aware.

Status Report

Published at 07:00 on 8 November 2025

Have been pretty quiet here recently. That’s because I’m focusing on other stuff, namely, getting this site out of the USA. Currently it is hosted at a server farm in the San Francisco Bay Area, run by a US-based cloud hosting company. Soon it will be hosted at a server farm in Quebec, run by a France-based cloud hosting company.

Also, my domain names are in the process of being cut over from being hosted by a US-based registrar to a Canada-based one.

Given the rapid progress of democratic decline in the USA, and the political nature of much of what I post here, such measures are, I think, only prudent.