Func Prog Conf 2026

Func Prog Conf 2026 logo projected onto an empty stage

Last Wednesday The Wednesday before last (fine blogging takes time to cook, you know), I attended Func Prog Conf here in Stockholm. It was my first time at the conference, having missed the inaugural instantiation last year somehow. In fact, I would have missed this year as well had not Arne texted to ask if I was going. I played it cool, "Maybe. Because I totally knew about this all along and I just wasn't sure if I could fit it into my awesome life with all the totally rad stuff that I'm always doing." Having maintained my street cred, I ran to my search engine of choice and tried to figure out what the hell he was talking about. 😅

It turns out that Func Prog Conf is a small one day event in Stockholm, just five talks and 180 people. It's organised by the great people over at Func Prog Sweden, who run a meetup group with an interesting twist: every other meetup is online, so they're able to have speakers from all over Europe (and occasionally further afield). Their YouTube channel is definitely worth a look. They are quite ecumenical, with talks from the hardcore type enthusiasts to the Lisp hippies with their laid-back approach to the serious engineers who are down with OTP (yeah you know me). I'd definitely recommend checking out their next meetup, whether in person if you happen to be in Stockholm, or streaming live on YouTube if you happen to be in a compatible timezone or a shifted sleep schedule or high on life or whatever.

Anyway, back to the conference. It was held at a really cool venue in Slussen called Kägelbanan, high up on the cliff overlooking the Baltic Sea. It's part of the Södra Teatern complex, which has a really nice brunch on Sunday mornings. Definitely worth a visit in the summer, as much for the view as the food itself.

Sorry, I just realised that I went on a tangent again when I really really intended to talk about the conference itself. 🤦🏼

Oh wait, there's just one more thing. 😅

Just one more thing

The story of the conference actually starts the day before, at least for me. You see, our local Clojure group, sthlm.clj, had organised a Func Prog Conf Prep on the previous evening, which I only found out about because Arne mentioned that he would also be there (with customary humility, he didn't mention that he was giving a talk at the meetup, of course). The meetup was scheduled to start at 16:00, and I was just a tiny bit late due to a frenetic work schedule (every manager knows that the pleasure of taking a day off is accompanied by the pain of having to shift all of the work you would have done on that day to other days). When I walked in a few minutes after 16:00, there was already a talk underway. I slunk into a seat in the back row, eyes downcast as I radiated shame.

Safely ensconced in my seat, I finally looked up at the speaker, and got a lovely shock as I realised it was none other than Christoph Neumann, Clojure developer advocate and all around fine fellow. It turned out that Christoph was doing a run-through off the talk he would be presenting at the conference the next day, a fact to which I was not privy, due to me not having actually read the speaker lineup for the conference.

After he finished, I went over to say hi, and right around the same time, Arne rolled in. Hugs were dispensed, conversation flowed, and the food arrived. As we were chowing down and chatting, Arne said something about his talk, and when I asked for clarification, it turned out that he was giving a talk at this very meetup, a fact to which I was not privy, due to me not having actually read the speaker lineup for the meetup.

If one were feeling particularly generous, one could describe my approach to life as being in the moment; whereas a more ungenerous interpretation would go more along the lines of wtf is wrong with you Josh do you actually read bro?

I throw myself upon the mercy of the readership to adopt a view more akin to the generous one. 🙏

Anyway, as I said, much milling about was occurring, and I made another astute observation:

A man wearing a shirt that says "we do it with rich comments"

Christoph was wearing a Calva t-shirt with a wicked awesome Clojure in-joke! Readers of the Clojure posts in this blog are likely already familiar with the Rich comment, but for those who aren't:

"These comments are rich because they provide rich detail about the development process and because they were written by a person named Rich."

There's a good explanation of Rich comments on the Between Two Parens blog, which I encourage y'all to read.

19:00 arrived, and with it, the first of the evening's two talks: Markus Holmström's: Cellsify – A take on Spreadsheets you didn't expect and now you need it in your life. This talk was as funny as it was mind expanding (spoiler alert: it's spreadsheets all the way down), and the second it was over, I DM'd Markus on Clojurians Slack to invite him on defn.

Next up was (a.k.a Arne Brasseur a.k.a. plexus), with Datastar – how to use it with Clojure and some of the architectural choices. I had read some about Datastar, but had gotten it confused with some other frontend thingy that used Datalog that was maybe developed by Roman Liutikov but maybe not since I can't find it in my memory or in my search engine... send paramedics please!

But like, yeah, Datastar. Seems pretty cool. But don't take my word for it; watch the talk! 😉

Even before the applause died down, I was on my feet, sprinting out of the Agical office and through Gamla Stan to catch my train.

I shall spare you the details of the rest of my evening (don't worry, I caught my train) and finally get around to talking about the conference itself.

The conference itself

Fast forward then to the next morning. The doors were set to open at 08:00, so I got myself to Slussen in good time, then walked up to the venue and arrived at about 07:50. Being a good Swede, I lurked just outside so I could be exactly punctual—not a minute early, not a minute late. Unfortunately, I rolled a 5 on my lurk check, and was detected by one of the Kägelbanan staff, who was out on the terrace in front of the venue having a crafty cig. Like, a real cigarette, with tobacco and all, not one of those new-fangled e-cigarettes that all the damn kids are puffing away on these days (get off my lawn, you damn kids!). That was surprising, but super cool, because you rarely see people going full James Dean in Stockholm anymore.

Even more surprisingly, she struck up a conversation with me. 🤯

You see, Stockholmers rarely so much as make eye contact with strangers, and never actually say so much as "hej" to them (unless out hiking, in which case they are downright friendly; or neighbours, in which case they might give a curt nod, a "hej" if they're feeling friendly, or even a "hej hej" if they're high on ecstasy or whatever). I guess this woman was primed for interacting with a bunch of foreigners (or maybe high on ecstasy, I dunno), but converse she did. I stumbled through the conversation in my barely functional Swedish, thinking I was getting away with it until she asked "Pratar du engelska på jobbet eller?" I hung my head and admitted that yes, I did in fact speak English at work, and yes, I was embarrassed that I hadn't learned Swedish in my 16 years here. Luckily, she wasn't the SD type, so she let me off the hook with the standard "Men svenskar alskar att prata engelska, så bli det tufft att lära sig svenska." I nodded, still appropriately ashamed of my laziness.

Anyway, we chatted away for a few minutes, then she told me it was actually OK to go in a couple minutes early (and by this, I mean a literal couple, since it was 07:58). I thanked her effusively, then headed inside to find my badge. I said hi to Magnus, one of the organisers of both the Func Prog Sweden group and the conference itself, and he told me that I wasn't in fact the first attendee to arrive—apparently someone else had been there since just after 07:00!

Grabbing my badge, I headed into the mingle area and armed myself with a coffee and a nice breakfast roll. I spotted Felix Alm setting up the Multiply booth, and walked over to chat. A few more people started arriving, and I had a really nice chat with a guy named Mauricio about Scala and Clojure and Lisp and programming philosophy and so on. He helped me distribute some defn and Pitch stickers whilst we talked, then finally it was nearing 09:00, when the conference officially kicked off.

People mingling

I made a beeline for the auditorium so I could get the perfect seat (third row, right side, aisle), and luxuriated in the sounds of silence as I checked out the setup. After a minute or two, Magnus walked out on stage and gave his opening remarks one last look as people started to file into the auditorium and find their seats. I snapped a quick picture, then whipped out my trusty Babashka-branded notebook and settled back in my seat, ready to be entertained and educated by the stellar lineup of speakers that had been assembled for the day.

A man stands on stage, studying his phone as he prepares his remarks

Christoffer Ekeroth from Functional Software (a Swedish recruitment agency specialising in functional programming roles) appeared in the wings, surveying the crowd. When he felt the moment was right, he strode onto stage and with a gesture, invoked the spotlights. He and Magnus assumed b-boy stances (OK, maybe that was just in my mind) and a hush fell on the crowd. They kicked off the event by introducing themselves, giving a brief history of the conference, and introducing the sponsors.

Two men on stage

After brief remarks from each sponsor, it was time for the opening keynote: "Transforming Software Evolution: Lessons from 10 Years of Clojure in Production", by Adam Tornhill.

Transforming Software Evolution

Adam Tornhill prepares to start his talk

I learned two things in the first 30 seconds of Adam's talk:

  1. He is a Clojurist (which I learned from his title slide)
  2. He is a Swede

The reasons for the first one were twofold: I hadn't actually looked at the talk lineup before the conference (as mentioned above), and another super embarrassing reason that shall be revealed presently.

The reason for the second one was far simpler: I had never seen Adam speak or heard him interviewed on a podcast (the former is now solved, whilst the latter is pending).

So anyway, in that first 30 seconds, Adam introduced himself, then started walking us through his path to Clojure. Apparently he got started pretty early!

A toddler holding a copy of the "Practical Common Lisp" book

It turned out that this precocious hacker wasn't Adam, but his son. Shortly after this picture was taken, his son started tearing pages out of the book, which Adam noticed were from the section on Common Lisp's type system. "So he was way ahead of me," Adam noted, drawing a chuckle from the crowd and a few mock scowls from some of the hardcore Haskellites in the crowd. Ah, 'twas all in good fun, 'twasn't it? A friendly trolling amongst friends, nothing more. 😉

Adam presents a slide labelled "My Road To Functional Programming"

There were many parallels to my own introduction to programming, which started out early in life on a primitive but beloved machine on which we used primitive but beloved programming languages (assembly, C, and Pascal for Adam; Motorola 6502 assembly, C, and BASIC for me), then moving on to slightly less primitive but slightly less beloved languages like C++ and Java, before reading Paul Graham's "Beating the Averages" essay (which I won't link to here because Paul Graham is an odious person) and seeing the Light of LISP. This is where our paths diverged a little bit, as Adam went for Common Lisp, even writing a book entitled Lisp for the Web (which you can access on the web for any price between 0 - 20—your choice!), whereas I went for the elegant weapon for a more civilised age that is Scheme.

I loved me some Scheme, but knew that I wasn't likely to be able to use it at work (even though one of my colleagues was writing a Lisp implementation in C++ as a hobby project at the time), so Lisp remained merely a source of personal pleasure for me. Until 2009, that is, when I encountered Stuart Halloway's "Programming Clojure". Lisp on the JVM sounded like a thing I might be able to sneak in, especially given the fact that my company was in the midst of a massive migration from Perl (yay!) to Java (less yay, but still OK). But then I moved from Japan to Ireland, trading a Perl-but-soon-to-be-Java team for a team doing operations for a big C++ search engine with many lovely Bash and Perl scripts, so poor Clojure had to wait.

It was somewhere around 2012 that I first used Clojure at work, building an end-to-end testing system for our product. Judging from his timeline, it seems that Adam was getting into Erlang and C# around the same time. In late 2013, I took my first real Clojure job, building the backend of a rock'n'roll trivia game in Clojure on AWS. Sometime in the next year, I too picked up C#, writing the network stack for our game's new frontend, which was built on Unity. I actually used Clojure there too (unbeknownst to my colleagues), thanks to Tims Gardner and Ramsey Nasser's amazing Arcadia, which was a port of ClojureCLR to Unity. 🤯

Thanks to Acadia, I was able to sit in a REPL and use the powers of interactive programming to prototype a network stack, one evaluated S-expression at a time. Oh happy times! That is, until I had to take my pristine Clojure code and translate it into C#. 😢

Whilst I was messing around with Unity, Adam was writing a book: Your Code as a Crime Scene. As a brief aside (surprise surprise) I just love the description of the book:

Jack the Ripper and legacy codebases have more in common than you’d think. Inspired by forensic psychology methods, you can apply strategies to identify problems in your existing code, assess refactoring direction, and understand how your team influences the software architecture. With its unique blend of criminal psychology and code analysis, Your Code as a Crime Scene arms you with the techniques you need to take on any codebase, no matter what programming language you use.

I have a copy of the book, but have only read the introduction. Which is why I didn't realise that Adam was a Clojurist. 😬

But back in 2015, I didn't have a copy of the book, because I only heard about it somewhere in the Long 2020. What I did have a copy of in 2015 was Joe Armstrong's Programming Erlang. Why I had this is somewhat unclear to me. My friend Ryan had dabbled in Erlang back in the winter of 2000-2001, and gushed about lightweight processes and live reloading and supervisors and stuff, but when I looked at Erlang back then, I had never seen an immutable, functional language before, so it looked like complete gibberish to me (this was before the infamous Programming Languages course I took in university that made me a first-class Lisp Hater).

But taking a page out of Adam's book (in a metaphorical fashion, don't worry), I can examine the dusty crime scene that was 2015 and uncover some clues:

  1. The games company I was working for was rapidly running out of money
  2. One of the angel investors bought out the rest of the investors and laid off all of the engineering staff but me
  3. That guy was a real d-bag
  4. I had grown to hate my job
  5. I wanted a new job
  6. Recruiters could sense this
  7. One of the companies the recruiters aimed me at was this Swedish fintech that had the world's largest Erlang system and employed all the Erlang developers in Stockholm and the surrounding environs
  8. I figured I should learn Erlang if I was interviewing for a job as an Erlang developer
  9. The way I learn a new programming language is to read the book first, then work through some of the more interesting exercises in the book, then write a somewhat non-trivial system using that language (these days, I write a Scheme implementation; back then, I guess I wrote some sort of webservice that did something something?)

From this evidence, I can surmise that I bought the book because I wanted to learn Erlang. And I did get an offer from that fintech, but I decided instead to join a streaming TV company to do Scala webservices (I actually did know Scala, having worked with it professionally for about a year at the same company where I built that Clojure end-to-end testing thingy). Of course, when I started at that company, I was dropped into a team that did low-level video transcoding in C and Python. But then we got this potential deal with a big TV company to do video on demand, and to win the deal, we had to demonstrate that we could transcode and stream arbitrary titles from their catalogue, and we had a week to do it. So I reached for the most obvious tool: Pixie. 😅

You see, this was many years before Babashka would make it possible to write Clojure shell scripts that started up immediately, and many many years before babashka.ffi, and I needed to call into libffmpeg from my scripts (I actually ended up abandoning that and just shelling out to the ffmpeg command-line tool).

The team I was part of consisted of me, two hardcore Finnish consultants who worked remotely from Helsinki, and this Swedish guy who worked together with me in the Stockholm office. At that point, I had been working for the company for maybe three months, and I had learned a little bit about video streaming (I had worked with my Swedish colleague on a DASH server in Golang) and maybe a little bit more about video transcoding, but I wouldn't really say I knew what I was doing.

Somehow, we made enough progress that we were very close by Wednesday morning. But not quite there. And the company we were trying to win the deal with was based in Qatar. And the Qatari working week runs from Sunday to Thursday. Which meant that we had until Thursday morning to have a working demo of our system. 😱

So my colleague and I loaded up on coffee and sat down at my desk and started what would turn out to be a nearly 15 hour pairing session. I would hack some Pixie, then he would take the keyboard to tweak our DASH server, then we'd switch again for more Pixie, then we'd get stuck and ping the Finns on our IRC channel (I think it was still IRC back then, but maybe we had Slack?), and they'd give us some ffmpeg incantation that was waaaaay over my head and just grazing the top of my Swedish colleague's head, and then back to the DASH server, and so on and so forth.

Around midnight, we successfully ingested, transcoded, and served our first video asset (I seem to remember it being a Champions League match). By 1 AM, we were scratching our heads wondering why the second asset we tried didn't work. But by 2 AM, we had fixed that, and by 3 AM, we had ingested five assets in a row, chosen completely at random (by shuffle-ing a list of asset IDs, natch). By 4 AM, I was in bed, trying to convince my caffeine-addled brain to stop projecting ffmpeg commands on the inside of my eyelids. And by 10 AM, I was somehow back at my desk, giving our demo system one last poke before we sent it over to the client.

And it worked! And we won the deal, which wouldn't have been possible without Lisp. So naturally, when it was time to build the production version of the system, we chose to do it in... Elixir. 😂

It turns out that my Swedish colleague had an irrational fear of Lisp, and an undying love of Ruby, and the things I loved most about Clojure were functional programming, immutable data structures, and interactive development, so we compromised on a language that had all of those things for me and looked a lot like Ruby for him.

It was the best decision we ever made. Elixir was absolutely perfect for the task. We had a set of processes that scanned the catalogue for new assets, then fired events to another set of processes that downloaded the assets, then another set that transcoded downloaded assets, and of course a DASH server. We built the thing interactively in Emacs with the amazing Alchemist.el, and after the first week of development to get a skeletal cluster up, we didn't restart the system more than once or twice in the three months it took to finish the thing.

Try that with C++, I dare you. 😉

But anyway, back to 2026, and this functional programming conference that I'm allegedly writing about (though there is a reason I took the Elixir detour, I promise). 😅

Like I said, there are a lot of parallels in Adam's and my roads to Clojure, but there's a decisive split circa 2025, when Adam Go(es) agentic and Rusty, and I very much don't. As I mentioned, I had done some Go at the video streaming company, with very mixed results. On the one hand, writing a service that listened to UDP multicast from a satellite downlink station and served it up on a TCP socket was like 50 lines of code. 🏆 On the other hand, writing a DASH server that read some JSON and then generated an MPD manifest was like a hundred million lines of code. 😭

And Rust? Well, if I was still doing much systems programming, it seems like a reasonable choice, and there's some really interesting stuff in the language, but my few forays into the community surrounding the language have left me with an incredibly bad taste in my mouth.

And agents? Well, any Clojurians reading this probably know how I feel about LLMs (a scourge upon humanity, etc). But more on this anon.

What Adam is doing in this talk is explaining why Clojure was a great choice for building CodeScene, the system he built for analysing the health of big codebases. And one of the key characteristics of Clojure is that it's a functional programming language. And a functional programming language is...

Adam presents a slide labelled "What's Functional Programming"

Well, what exactly? As Fogus and chouser quip on this slide, it's not an easy question to answer:

"If you ask 100 programmers for their definition, you'll likely receive 100 different answers."

But Adam actually answers the question quite succinctly on his previous slide:

A slide labelled "Functional programming benchmark"

Less code, more features, more fun... in Erlang, that is. In Clojure, it's more fn, proving once again its superior expressiveness. 😉

Interestingly enough, Adam is trained as a psychologist. So of course he had to give us an IQ test, showing us a set of patterns with one missing, and asking the audience to shout out the number corresponding to the missing pattern.

It started out with a reasonably straightforward one:

A slide labelled "Let's do an IQ Test"

Got it? Many people in the audience did too, yelling out "8" with gusto.

But then, the friendly IQ test turned into this:

A slide labelled "...and a slightly harder test"

Adam presents a slide labelled "...and a slightly harder test"

If you struggled with this one, you are far from alone. Only one brave voice in the audience called out the answer (which is 5).

Having humbled us with the IQ test, Adam made a recommendation: "Do not turn your code into an IQ test." Sage advice indeed!

He then explained the goal of Code Health, the central concept behind the CodeScene platform he had developed in Clojure: to bring visibility to code and code quality:

Adam presents a slide labelled "Code Health: bring visibility to code and code quality"

At a high level, what CodeScene does is:

  1. Parse the source
  2. Identify code smells
    • Module / class level smells: e.g. low cohesion, God Classes
    • Function level smells: e.g. copy-pasted logic, God Functions, primitive obsession
    • Implementation smells: e.g. deep nested logic, complex conditionals
  3. Score, aggregate, and categorise:
    • 💚 Healthy code with low risk defect
    • ⚠️ Increased maintenance efforts
    • 🛑 Unhealthy code with significant issues and defect risks

This allows CodeScene to build really cool visualisations to identify areas of the code where technical debt is lurking. Of course, when you have a massive codebase like the Linux kernel, with 21.4 million lines of code, contributed by over 15,000 authors...

Adam presents a slide labelled "The Need For Concurrency: Analysing massive codebases"

...you can't exactly just

(map calculate-code-health-of files)

Of course, with Clojure, you can just add a character to turn the serial into the parallel:

(pmap calculate-code-health-of files)

According to Adam, "That single character gave me a 10x speedup. It was the most efficient character I've ever written!"

But other than the magic of the letter p, what does Adam look for in a programming language?

Adam presents a slide labelled "What do I look for in a programming language?"

When he first chose Clojure for CodeScene back in 2015, it was:

And in 2026, with his agents:

Clojure still wins.

Anytime I write the word "AI", I of course need to give the 🤮 disclaimer.

Here's a fun code health problem for us:

Adam presents a slide labelled "Meet a Code Health problem: Deep Nested Complexity"

Looks like Ryu needs to learn recursion. 😂

One way to think about programming is that you have two models:

  1. A situation model, which is the programmer's mental representation of the problem domain
  2. The corresponding system model, which is how the programmer models the domain in software

Adam presents a slide showing a diagram of situation model and system model

The situation model is used to express knowledge, which is encoded in the system model, then data is input and the outcome is observed by the programmer, allowing them to update their situation model (this is where learning occurs). The bigger the gap between these two, the more cognitive load is placed on the programmer, thus increasing the chance of defects in the system.

The programmer's goal then becomes to close the gap between the two models, and one way Adam proposes to do this is to build domain-specific languages, such as:

(defn costs-by-file
  "Given a sequence of task durations (e.g from Jira),
   what are the development costs per file?
   Development costs are expressed in work days, wd."
  [duration-by-task]
  (->> duration-by-task
       (map (partial assign-to-files file-name->ticket))
       (filter passes-minimum-thresholds?)
       (reduce by-file-name)

And you can take this a step further with an embedded DSL, using the great and terrible power of macros!

Gandalf saying "I would use this macro from a desire to do good..."

You could define a macro along these lines:

(defmacro enable-code-health-suppressions-for
  [& suppressions]
  (->> suppressions
       (map (fn [s]
              `(defmethod apply-directive-to ~s [parsed-code#]
                 (apply-shared-logic parsed-code#)
                 (remove-warning ~s parsed-code#))))))

And then write code like this:

(enable-code-health-suppressions-for
  :complex-method
  :bumpy-road
  :deep-nested-complexity)

which would expand at compile time to this:

(defmethod apply-directive-to :complex-method [parsed-code]
  (apply-shared-logic parsed-code)
  (remove-warning :complex-method parsed-code))

(defmethod apply-directive-to :bumpy-road [parsed-code]
  (apply-shared-logic parsed-code)
  (remove-warning :bumpy-road parsed-code))

(defmethod apply-directive-to :deep-nested-complexity [parsed-code]
  (apply-shared-logic parsed-code)
  (remove-warning :deep-nested-complexity parsed-code))

So it looks like macros can be used for good after all... for a time. But continuing down this road leads to Common Lisp, and Common Lisp leads to:

Cover of the book "Let Over Lambda"

Adam's claim is that judicious use of macros can move the programmer from instructing a machine (which is slow) to expressing a domain (which is powerful).

Adam presents a slide showing a diagram of moving from instructing a machine to expressing a domain

And all jokes aside, Clojurists do use macros, but as a tool of last resort. The Clojure philosophy is something like this:

  1. Use data whenever possible
  2. When you can't use data, use a function
  3. When you can't use a function, say a little prayer and use a macro

Whereas the Common Lisp philosophy is more like this:

  1. Use macros everywhere, especially reader macros, so you can write code that doesn't even look like Lisp anymore and is so powerful that no mere mortal can comprehend it

Having made a series of compelling points about how to keep complexity under control with the power of functional programming in Clojure and enticed us to try out CodeScene (I'm starting the free trial as soon as I have a few free days in my calendar to point it at my company's fairly large Java, TypeScript / JavaScript + React, and .NET codebases to see where be the dragons), Adam summarises why we should all be using Clojure in 2026 (🤮 disclaimer on the first point):

Adam presents a slide labelled "Why Clojure?"

This was a fantastic talk and a great way to kick off the conference! I would recommend that everyone watches the talk as soon as it goes up (and I'll try to remember to update this blog post with the link to the recording when that happens), but in the meantime, you can also check out Adam's slides.

After the thunderous applause died down and Adam answered a question from the audience (which I didn't note down, but I remember as being an actual question, not the infamous Tech Bro "Question") and folks started filing out, I took up my lurker's position near the stage, ready to intercept Adam before he could escape the auditorium.

I thanked him for his talk, admitted that I had only read the intro to his book, and invited him to come on defn and talk about all this awesome stuff. We're trying to find a date as I write this, so hopefully it works out and you'll have something to feast your ears on in a few weeks (and I'll try to remember to update this blog post with the link to the episode when that happens). 🎉

After a coffee break, the next talk began, and it was of a very different character to Adam's: Eric Torreborre's "Beyond the Expression Problem".

Beyond the Expression Problem

I have to admit that this one was tough going for me, so whilst the Haskellers and Scalars in the crowd nodded knowingly throughout, I took copious notes, which helps my brain decomplect.

Eric's talk was basically about the holy grail of compositional programming:

Eric presents a slide labelled "Compositional programming"

If you have no idea what that slide means, fear not! Eric explained it. And his explanation made sense to me at the time, but looking back at my notes as I write this, it seems that my absorption of the topic was limited to the absorption of ink into my notebook, and did not indeed penetrate my thick skull. Ah well, I can at least share a couple of slides that I enjoyed!

Eric presents a slide labelled "Modularity is great!"

Legos! And the Millennium Falcon! And the Millennium Falcon made out of Legos! And yes, that does in fact cost basically 10,000 Swedish Crowns, which as of this writing is about 900 Euros or 1000 US Dollars. 🤯

So modularity is good, but

Eric presents a slide labelled "In practice", showing a game of Tetris about to be lost

But not to worry

Eric presents a slide labelled "Modularity is difficult, but there's hope!"

Because the type system can save us!

Eric presents a slide labelled "In practice"

"That's a very simple lambda calculus in a way," quoth Eric, as my head exploded.

But then there's a twist: one has to actually implement this, which Eric illustrates as follows:

Eric presents a slide labelled "In practice"

Eric's face falls. "It sounds like the whole type system is useless." 😭

But there was a happy ending, and Eric concluded that it may be possible to implement this in a new programming language that he is working on together with some researchers.

Despite the type magic going a bit over my head, the talk was extremely engaging, and Eric got a few good questions at the end.

Mulling it over afterwards, I thought back to his explanation of the expression problem, which is that it's difficult to extend types and functions at the same time. Unless I'm missing something, it feels like Clojure makes this pretty easy: we have multimethods, which cover the most common cases, and protocols, which "avoid the 'expression problem' by allowing independent extension of the set of types, protocols, and implementations of protocols on types".

I was reminded of a Haskell team that I managed a few years back. They had a huge amount of fun, constructing elegant cathedrals of types and typeclasses and higher-kinded types to solve problems that they had created for themselves. Meanwhile, our stakeholders were becoming increasingly desperate for us to like actually ship the software so we could actually like solve an important problem for our customers.

I don't claim this is representative of static type enthusiasts working in industry, only that a significant portion of my interaction with the statically typed programming language communities (both at work and conferences) tends toward the esoteric and academic. And no shade, that's very interesting. I often enjoy Haskell and Scala talks at conferences (even when my comprehension level is usually 25% at best), and definitely like the vibe of a group of people excitedly expanding their minds in communion with each other.

But here's my problem: I've ended up in one too many conversations over the years where I magnanimously offer that statically typed and dynamically typed languages are equally valid, offer different tradeoffs, and ultimately tend toward the shape of the programmer's mind, rather than an inherent superiority of one over the other, only to be told confidently "you don't get it" (almost certainly true, but I feel that validates rather than invalidates my assertion), or "you probably just haven't worked on large enough systems to have seen the limitations of dynamic typing" (I always have to bite my tongue not to be That Guy™ and mention a certain e-commerce website that I worked on for a few years, in a dynamically typed language). I don't go around trying to convince people that Clojure is better than their favourite statically typed programming language, I just make the statement that Clojure is better for me than their favourite statically typed programming language.

Anyway, after this feast for the mind came a feast for the body, in the form of lunch. I had some kind of vegan salad thingy with falafel and other stuff, which was as delicious as a deftly placed defmethod, especially with a side of conversation with Arne and Christoph, which continued whilst relaxing on some comfortable sofas on a mezzanine overlooking the stage, which I must shamefully admit caused us to pay only cursory attention to Adam Warski's "The Scala 3 Features for Agentic Development, Today and Tomorrow" (🤮 disclaimer on the middle part of the title). But such is the cost of fellowship, and it's one I'll gladly pay!

The next talk, however, drew me downstairs and into the auditorium like a moth to a flame: Giuseppe Castagna and Guillaume Duboc presenting "All Set: Bringing Static Types to Elixir". See, I told you there was a point to my previous rhapsody on Elixir!

The iron fist of José Valim

Giuseppe being introduced by Christoffer Ekeroth

I absolutely loved this talk! Of course, I am extremely partial to Elixir. In fact, if every Lisp disappeared from the world tomorrow, I would shed a single tear, and then, like a Phoenix rising from the ashes, be reborn as an Elixir programmer.

The talk started with Giuseppe showing some code with type annotations in a comment above each function, but they were different from the type of type annotations (sorry, I promise that wasn't intentional) I'm used to seeing. In fact, these type annotations read more like pseudocode, which, like, I can get behind.

Giuseppe admitted that all wasn't rainbows and unicorns, however:

Giuseppe presents a slide labelled "Precise typing of pattern matching"

I mean... I can't help but deploy this meme:

Charlie Day gestures wildly in front of a board with papers connected by a web of red string

But wait, Giuseppe is about to turn my frown upside down!

"The hard part is to derive algorithms to decide if a type s is a subtype of a type t. But don't worry, we know how to do that, so you don't have to do it yourself."

Hurrah!

I don't remember the exact context for this quote, but it amused me enough for me to jot it down in my notebook:

"That seems silly, but is actually very smart."

The coolest part of the talk was when Giuseppe revealed Elixir creator José Valim's reaction to their work. "Very cool," quoth he, "but here are my requirements for adding it to the compiler":

  1. You don't have to annotate the entire codebase in order to start seeing benefits (gradual typing!)
  2. Types don't modify the runtime semantics of your program

The rest of the talk was about how they implemented their type system within José's constraints, and it was a very clever solution indeed, as it ended up not requiring any annotations (I think), but rather using type inference to make the type checking as strict as it could be whilst not pushing the programmer into that annoying situation where you know your code is correct, but end up arguing with the compiler for hours before giving up and just throwing an Any or void * or whatever at it just to shut it up.

They also measured the type checking time as a proportion of the overall compilation time, with the goal of keeping it under 10% (I think—I didn't write down the actual target, for some reason).

So yeah, great talk!

And finally, it was time for Christoph Neumann to deploy some game theory to help us navigate the challenges of industrial programming.

Infinite Coding

Christoph presents a slide labelled "Finite and Infinite Games"

Before revealing the meaning behind the titillating title of his talk, however, Christoph poses what I can only assume is a rhetorical question:

Christoph presents a slide labelled "What is your favorite programming language?"

But then, he posed a tougher question: if you could not use your favourite programming language, what language would you use instead?

This question was actually posed in the 2025 State of Clojure survey, and the top five answers were mostly unsurprising:

  1. Java - 11.40% 🤷🏼
  2. Python - 10.09% 🐍
  3. Quit programming - 9.89% 😲
  4. Elixir - 9.08% 💜💜💜
  5. TypeScript - 7.06% 😬

But wait, what's going on at #3 there?

Apparently, nearly 1 in 10 Clojure programmers would actually quit programming altogether if they could not use Clojure! 🤯

I'm one of the 9 out of 100 that would use Elixir (unless I could sneak Scittle or Babashka or Jank or Clojerl or Cherry or Squint past the Ministry of Love), as noted above, but I totally get the sentiment.

Most of the Clojurists in the audience had already seen this, either when the State of Clojure results were published back in February, or the day before during Christoph's dry run at the sthlm.clj meetup, but minds were clearly blown in the audience, and many a furrowed brow was spotted as Haskellers and Scalars contemplated life without their powerful types and slow compilers (sorry! I jest out of love for my fellow Functionalistas) and Elixirians despaired at the thought of letting it crash only to find it's unsupervised.

Having gotten the audience's attention, Christoph made a statement that I think everyone in the room would have agreed with two years ago: making software is hard. He then issued an update which I hope is uncontroversial amongst the people in the audience and readership of this blog, even in 2026: making excellent software is hard. If this is the case, a deeper question emerges:

Christoph presents a slide labelled "What makes software excellent?"

Christoph ended his talk early by just giving us the answer: functional programming! (and monads), drawing a hearty laugh from the crowd. But of course he wasn't actually done, and like the good Clojurian he is, he pointed out that there's no way to answer a question such as "what makes software excellent?" without defining the word "excellent":

Christoph presents a slide labelled "excellent = surpass, be superior"

And now it's officially a Clojure talk!

OK, but now that we know what "excellent" means, we must ask ourselves what our software should be excellent at. Christoph offers some common options:

But then there's a twist! Excellence at any of these matters not a whit if you're not solving real-world problems!

Christoph presents a slide labelled "Real-World Problems"

And to solve problems, we must make choices. But there's a paradox here: choosing an option reduces our options! 😱

There is a way to manage this paradox, though. If we separate our choices, make them truly independent of each other, a choice in one space only affects that part of the solution, leaving options open elsewhere. And this, my dear friends, is why we decomplect. If you're not a Clojurist, "decomplect" means something like "to take apart a complex thing by unbraiding it into its constituent pieces, each of which can now be used independently". I actually couldn't find a good reference for the definition, so if anyone reading this can point me at one, that would be wonderful. Rich Hickey does however clearly define the word "complect" in his epic Simple Made Easy talk: "to interleave, entwine, or braid". (By the way, there's an amazing repo on GitHub called talk-transcripts, which has full transcripts for loads of talks by such luminaries as Rich Hickey, Alan Kay, David Nolan, Guy Steele, Evan Czaplicki, etc.)

OK, back to Christoph. Having elucidated the paradox of choice and offering us a way out, Christoph asserts that changeability (and of course he includes a definition slide: the ability to make the changes that we want or need) is the central factor of longevity of an excellent codebase. Remembering the paradox of choice, one of the best design questions we can ask ourselves is "what choices can we defer?" I can't remember where I read this, but someone said that what we should be doing is not making choices at the last possible moment, but rather at the last responsible moment, and I think that's what Christoph is getting at here.

And now another definition. Optionality: preservation of choices. We want to preserve optionality for as long as possible responsible, allowing us to decide later when we have more information. Having now presented the concepts of changeability and optionality, Christoph tells us what they have to offer us:

And optionality is more important to us as programmers than changeability.

Finally, Christoph reveals why his talk is titled "Infinite Coding". In a book from 1986 called Finite and Infinite Games, the philosopher James P. Carse proposed that

all human behavior can be categorized into two types of play. Finite games, such as chess or politics, have defined boundaries, fixed rules, and clear winners, played with the sole purpose of bringing the game to an end. In contrast, infinite games, such as culture, love, and life itself, have evolving rules and open boundaries; they are played for the purpose of continuing play and welcoming new participants.

Christoph thinks this is a very useful theoretical construct for talking about programming, and he simplifies the concept for us:

Finite games have boundaries, such as time, rules, and players, whereas in order to keep playing an infinite game (which is the goal), the rules must change, and play is in fact threatened by boundaries of the sort imposed by finite games.

So what does this have to do with software?

Christoph presents a slide labelled "Working on software is indefinite, therefore an infinite game"

For systems that solve real-world problems, which tend to evolve over time, we want to be able to evolve our software for as long as the problem exists; in other words, we want to keep playing indefinitely. When our software becomes so rigid that we cannot change it anymore, the game ends, and we lose.

So what kinds of things end the infinite game of software?

Like all infinite games, as we play the game of software, we encounter many finite games along the way, such as:

As any programmer will attest, playing finite games is necessary. However, finite games may harm the infinite game, and it's possible to win our way into failure. What we want to do is to win the finite games we play, but choose to play only the ones that don't threaten the infinite game.

To keep the infinite game going, we want to:

To avoid the need to change, we need to identify the things that don't change, which is of course easier said than done. There is hope, however, as Christoph points us at a book by Morgan Housel called Same As Ever, and then offers some examples from the programming game:

Graph labelled "Clojure codebase - Introduction and retention of code"

Christoph now poses the question of what keeps the infinite game going? And then of course offers some answers:

But here comes the real world again:

Christoph presents a slide labelled "The real world threatens play"

To play any game, we need a good strategy, and Christoph proposes one here:

By applying this strategy skilfully, we can maximise both changeability and optionality.

Christoph presents a slide labelled "Maximize changeability and optionality"

And now for Christoph's mic drop moment:

We are human. Playing must be fun and worthwhile!

🫳🏻🎤💥

As you may have gathered from the number of words I expended writing about this talk, I thoroughly enjoyed it. My notes runneth to five pages, and verily did I consult Christoph's slides to make sense of them.

With that, the conference was over... except it wasn't!

The aftermath

Onstage from left to right: Giuseppe Castagna, Guillaume Duboc, Eric Torreborre, Adam Warski, Christoph Neumann, and Christoffer Ekeroth

The organisers gathered most of the speakers onstage for a panel discussion, which was lively and fun, with some disagreement expressed cordially. I wish I had taken notes, because I don't remember many of the questions (one was something like "what is the future of functional programming?" and I'm sure there was an "AI all the things?" 🤮 one in there somewhere) or answers, but I do remember one of the panellists saying something about mutability and me getting so excited that I literally pointed at Christoph, willing him to mention transients in transducers, and getting even more excited when he asked for the mic, then less excited when he said something awesome but not as awesome as transients in transducers. 😂

Finally, Christoffer thanked the speakers, shooed them off the stage, and gave some closing words. Amongst those closing words were words hyping up some upcoming conferences, and amongst those were the EuroClojure 2027 reboot (May 19-21 in Prague), and Arne's own HeartConf, the expansion of the legendary Heart of Clojure conference (August 18-19 in Mechelen, Belgium).

Christoffer in front of a slide displaying the lineage of HeartConf

I'll definitely be at HeartConf (I've already got several ideas brewing, just waiting for that sweet sweet CFP to open)—whether that's an enticement or deterrent I can't say—so hope to see you there!

With that, Christoffer thanked the sponsors for making the conference possible, the speakers for making the conference contentful, the organisers for making the conference, and the audience for making the conference awesome. He all but promised that there will be a Func Prog Conf 2027, and after basking in a huge round of applause, released us to go mingle. Which we did. My social batteries were running low, but I did have just enough juice to grab some juice of the barley (big thanks to the organisers for making sure non-alcoholic beer was available!) and making one last circumnavigation of the mingle zone, saying my thank yous and goodbyes and exchanging LinkedIn profiles and email addresses and Clojurians Slack usernames.

Arne was also feeling the need to recharge, so the two of us shook hands with Christoph and Magnus on our way out the door, then strolled through Södermalm to the place where Arne was staying, taking in the scenery (the clouds had parted and the sky was blue, though rapidly turning into dusk because it was after 17:00 in Stockholm in October) and enjoying some relaxed conversation which was not about Trump or AI (the rules of engagement at the Belgian Clojure meetup in Leuven, if you ever happen to be in the neighbourhood), then finally parted ways, he turning rightwards and I trying to orient myself in order to locate the nearest tunnelbana station.

I had done a pretty good job of keeping my phone in my pocket (except for photos and networking) and my attention in the moment all day, so I resisted the urge to whip out Organic Maps, and instead ducked into a restaurant to actually ask a human being for directions. The human was most obliging, and pointed me "rakt fram" down Folkungagatan, and I enjoyed a leisurely 20 minute stroll through the heart of Söder, the lights coming on as the sky darkened, people going about their business, bicycles cruising past; in short, the city breathing.

What a lovely end to a lovely day.

🏷 clojure conferences
📝 Published: 2026-10-25
📣 Discuss this post here
⏪ Why can't I just run around Lake Mälaren?