AI agents, Haskell, and the stubbornness of developers

Recently, I found an article about a member of the Haskell Foundation – who was moving his company away from Haskell. The company built a hardware product with Haskell, and they were moving away reluctantly.

I’m not going to repeat the whole thing here (you can read it yourself, but the TL;DR; is: the Haskell compiler and tooling ecosystem was too slow, and that became a bottleneck now that the LLM agent writing the code is so fast.

Now, let’s be clear: I don’t want to start a holy war about “static versus dynamic typing”, so I’m not going to do that. I’m not going to discuss if the merits of static typing are overrated or not, and I’m not going to discuss if dynamic languages are more or less flexible. This was discussed over and over again – and nobody knows the result. And for me, that in-determination is also a result.

What I am going to talk about is the stubbornness of software developers. It’s something that’s been bothering me for a couple of years now, and it still bothers me today. Looking at this article was no different.
(more…)

When everything becomes relative to AI

I have to be honest: I feel I’m taking crazy pills recently.

There were a growing number of posts, in the past, praising AI for coding; then, it started to grow, and grow, and now, on LinkedIn, almost all the posts that come to me are about AI and coding, how good they are, how the “game has changed”, etc, etc, etc.

But here’s the catch: every bad practice that we fought against, over and over, for literal decades is now being praised because “AI is doing it”.

Every. Little. Thing.

From the most obvious to the less, against all good judgment, against academic research that shows that AI usage decreases contribution between coworkers, or that they make programmers slower while they think they are faster, that the code quality is lower, or that it makes people work longer hours, it seems that all rules are off when it comes to AI.
(more…)

I have to be honest: I feel I’m taking crazy pills recently.

There were a growing number of posts, in the past, praising AI for coding; then, it started to grow, and grow, and now, on LinkedIn, almost all the posts that come to me are about AI and coding, how good they are, how the “game has changed”, etc, etc, etc.

But here’s the catch: every bad practice that we fought against, over and over, for literal decades is now being praised because “AI is doing it”.

Every. Little. Thing.

From the most obvious to the less, against all good judgment, against academic research that shows that AI usage decreases contribution between coworkers, or that they make programmers slower while they think they are faster, that the code quality is lower, or that it makes people work longer hours, it seems that all rules are off when it comes to AI.
(more…)

The “Jankiest” way of writing Ruby gems

Recently I wrote about a Jank, the programming language that is able to bring Cojure to the native world using LLVM. I also mentioned that Jank is not yet ready for production usage – and that is just true; it still have many bugs that prevent us to use it for more complex problems, and maybe even some simple ones.

That doesn’t mean we can’t try it, and see how bright the future might be.

At my last post I ended up showing in an example of a Ruby code. Later, after many problems trying to make something more complex, I finally was able to hack up some solution that bypasses some of the bugs that Jank still have.

And let me tell you, even in the pre-alpha stage that the language is, I can already see some very interesting things – the most important one being the “interactive development” of the native extension – or if you want to use the Ruby terms, monkey patching native methods.
(more…)

Calling Jank from C

For those that don’t know, Jank is a Clojure implementation but instead of targeting Java, it targets LLVM (Low-Level Virtual Machine). That means, Jank compiles to native code, and interops directly with C++.

Jank already have ways to call C++, but I wanted to do the opposite – to call Jank’s code from C. The reason might not be obvious, so here is an why: writing libraries.

Not all things need to be “stand-alone executables”. One example is libraries for Node, for Ruby, or Python. These languages are amazing on the levels of abstraction they support, and it’s easy to interact directly with code and their runtime (in Node, using Devtools, in Ruby, using something like pry or Lazuli, my own plug-in). They are also quite slow, and in some cases, we might need to call some native API that these languages don’t support. So what now? The canonical way is to write some extension in C or C++; now we have to manually manipulate memory and deal with safety issues (and before people say something about it “not being that hard”, it is. Most of CVEs happen because of manual memory manipulation in C – every cast, every printf, every strcpy can cause ACE and/or privilege escalation issues). They are also not interactive so if you’re trying to easily hack some solution, you need to write the code, compile, make a shared library, use the library via the Ruby/Node/Python code, see if it does the thing you want, repeat.

It’s tedious. Maybe with Jank we can speed up this process?
(more…)

Linux, Wayland, and NVidia.

For some time, I’ve been trying to run my Linux under Wayland. It’s… always complicated. VERY complicated.

I have what people call the “unholy trinity” – Wayland, NVidia GPU (in a laptop to make things worse), and I use an Electron app (Pulsar). Pulsar is my main editor, so it’s basically “the reason I use a computer most of the time” really.

So it was a good surprise when I found out that things work… except…

Gimp.

And Darktable.

These flickered like crazy. And because they are image editors, this flickering is insane – it makes editing things essentially impossible (imagine you’re adjusting brightness and the screen is flickering between darker and lighter, and then stops… in the wrong frame, meaning you have no idea if it’s correct or not). So I tried to track the problem, and I finally have a solution (hopefully). This post will give the results, but the TL;DR; is – update your Linux (Ubuntu 24.04 is the MINIMUM version that you need), update your KDE to at least 6.2 (or use some recent desktop env with good wayland support), don’t use the Open Kernel NVidia driver, and update your Xwayland to at least version 24.0.
(more…)

Exposing Clojure to Ruby and other languages – Java objects in C

In the first post of this series we decided to compile a Clojure library to a native shared library (with the GraalVM native-image command) and we used “isolates” so that a “global variable” in Clojure (and Java) would appear as if they’re “local” in Ruby. Then on the second post of the series we decided to make things local, and instead of “making a resolver then storing it in a global variable” we decided to “make a resolver and return it to Ruby”, and to abstract the nature of “callbacks” we used a CFunctionPointer in the Java side, and we sent the “block” from Ruby as an “opaque object” in Java, using GraalVM’s VoidPointer object.

Now, we need to do the opposite – we need to return a “resolver” to Ruby, and then we need to make a “List of Resolvers” in Ruby-side, and send it to Clojure-side somehow. These Clojure/Java objects (a Resolver, and a List of Resolvers) will also be “opaque objects” in C (meaning – we’ll receive them as void*, because they can’t be represented in C-land, nor in Ruby-land), but only in C – in Java-land (and Clojure, by definition) they’ll need to retain their types. The object GraalVM provides for this task is an ObjectHandle.

We’ll also fix a lot of memory leaks, so let’s move on!
(more…)

Exposing Clojure to Ruby and other languages – Callbacks

At the first part of this series I showed how to expose some Java methods (that delegates to Clojure functions) to a shared library, so that the shared library could be exposed in Ruby via the C bindings. There is a lot of “cutting corners” on the first implementation, for example, we only transmitted strings that would be serialized and de-serialized between languages, and the fact we’re using GraalVM “isolates” to allow multiple instances of “VMs” to exist, so we can fake having multiple objects, etc. In this post, I will fix some of these issues, and then show how to expose complex objects.

So, here’s a quick overview of the Clojure library I want to expose: the library allows you to define “resolvers”, which are functions. The difference between a resolver and a “normal function” is that the resolver always expects and returns a “Map” (HashMap in Ruby). The resolver also have some “metadata” that explains, at least, the dependencies: meaning, what are the keys that the “input” of the resolver must have, and what are they keys that the “output” will return.

The implications of this are huge, although they might not appear so – the idea is that, instead of wiring up things manually (like, for example, querying a database, getting the result, sending to some external service, get the result of the service, do something else) you just define the “dependencies” – for example, “I need the user’s login and email for this external service” as a “resolver” – if hashmap doesn’t have it, you’ll have a different resolver saying “Query the database and return the user’s login and email” and so on.
(more…)

Exposing Clojure to Ruby and other languages

Recently, I’ve been missing Pathom (from Clojure) in the Ruby world. So I decided to check if I could expose an arbitrary Clojure library to Ruby, using the GraalVM’s “Substrate VM” (popularly known as native_image).

The way I tried to do this was to expose a shared library to C, then making a Ruby extension that consumes this shared library and then finally “normalize stuff” into Ruby. This… honestly, worked way better than I expected, and because I needed a lot of help from AI tools, guesswork, and reading some very weirdly-written Java code from Oracle (and auto-generated Javadocs) I decided to make a post explaining the whole process.

The whole experience started as weird, then easy, then VERY hard, and right now… I’m not sure where it will be, because I’m kind of changing the whole project’s core ideas (the reasons will be clear while you read this post). So let’s dive in
(more…)

Quick Post – Multiple Shadow-CLJS builds at the same runtime

One of the greatest limitations of ClojureScript is how you can’t have two ClojureScript codebases, running on “development mode”, in the same runtime. In the browser, or in Node.JS, this is not a big problem, but it is one in some other situations – like browser extensions (you might be developing two extensions at the same time), node libraries (again, same case) and… well, editor plug-ins for Pulsar, or VSCode.

That… might not be a problem anymore.

If you use Shadow-CLJS (and you should) then you can just change your target to :npm-module (or :esm if you’re in the browser). That will create a lot of files but the important one is cljs_env.js. What this file does, is bootstrap the Google Closure Compiler and make some assignments for Shadow and for ClojureScript namespaces.

In the beginning of the file, you’ll see this line:

var CLJS_GLOBAL = global;
var $CLJS = CLJS_GLOBAL;

Just change it to:

global.some_unique_identifier = {}
var CLJS_GLOBAL = global.some_unique_identifier;
var $CLJS = CLJS_GLOBAL;

And that’s done.
(more…)