# Clojure

Clojure is a dynamic, general-purpose programming language designed for functional and multithreaded programming.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Clojure/Conj 2026 Will Offer Free Online Streaming to Broaden Access

DevFeed: [Clojure/Conj 2026 Will Offer Free Online Streaming to Broaden Access](<https://devfeed.tech/articles/why-this-year-s-clojure-conj-matters-beyond-the-conference-38855.md>)

Original publisher: [Read original article](<https://building.nubank.com/why-this-years-clojure-conj-matters-beyond-the-conference/>)

Author: Nubank Editorial

Published: 2026-09-11T17:39:44Z

Content type: opinion

Language: en

Sources: [Nubank](<https://devfeed.tech/sources/nubank.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Functional programming](<https://devfeed.tech/topics/functional-programming.md>), [coding-community](<https://devfeed.tech/topics/coding-community.md>)

Tags: [analytics-engineering](<https://devfeed.tech/tags/analytics-engineering.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [data-science-machine-learning](<https://devfeed.tech/tags/data-science-machine-learning.md>), [developer-community](<https://devfeed.tech/tags/developer-community.md>), [free](<https://devfeed.tech/tags/free.md>), [technical](<https://devfeed.tech/tags/technical.md>)

### AI overview

This commentary explains how free online streaming for Clojure/Conj 2026 can make technical discussions accessible to developers who cannot travel or afford in-person attendance. The conference will take place from September 30 to October 2 in Charlotte, North Carolina.

### Source excerpt

Making technical knowledge more accessible strengthens the entire developer community The post Why this year's Clojure/Conj matters beyond the conference appeared first on Building Nubank.

## Migrating from a Monolithic Orchestrator to Apache Airflow

DevFeed: [Migrating from a Monolithic Orchestrator to Apache Airflow](<https://devfeed.tech/articles/migrating-from-a-monolithic-orchestrator-to-apache-airflow-30518.md>)

Original publisher: [Read original article](<https://medium.com/helpshift-engineering/migrating-from-a-monolithic-orchestrator-to-apache-airflow-30fde94bcdc0?source=rss----3229f31ca4f4---4>)

Author: Poorva Patil

Published: 2026-06-03T09:20:17Z

Content type: article

Language: en

Sources: [Helpshift](<https://devfeed.tech/sources/helpshift.md>)

Topics: [airflow](<https://devfeed.tech/topics/airflow.md>), [Orchestration](<https://devfeed.tech/topics/orchestration.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Python](<https://devfeed.tech/topics/python.md>), [Monitoring](<https://devfeed.tech/topics/monitoring.md>)

Tags: [apache-airflow](<https://devfeed.tech/tags/apache-airflow.md>), [architecture](<https://devfeed.tech/tags/architecture.md>), [aws](<https://devfeed.tech/tags/aws.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [data-engineering](<https://devfeed.tech/tags/data-engineering.md>), [etl](<https://devfeed.tech/tags/etl.md>), [monitoring](<https://devfeed.tech/tags/monitoring.md>), [monolithic-architecture](<https://devfeed.tech/tags/monolithic-architecture.md>), [orchestration](<https://devfeed.tech/tags/orchestration.md>), [python](<https://devfeed.tech/tags/python.md>), [software-architecture](<https://devfeed.tech/tags/software-architecture.md>)

### AI overview

The article describes a migration from a monolithic Clojure-based scheduler to Apache Airflow. The legacy system coupled event pipelines, dependencies, and an EMR step, making workflows difficult to understand, maintain, monitor, and debug. The authors report that Airflow's Python-based DAGs made dependencies, retries, and scheduling more readable and helped improve onboarding and maintainability.

### Source excerpt

Photo by Corinne Kutz on UnsplashBefore we knew better Our orchestration system started as a simple internal solution to manage event pipelines and trigger downstream jobs. Over time, as more workflows and dependencies were added, it gradually evolved into a tightly coupled monolithic scheduler that became increasingly difficult to understand and maintain. Understanding how a workflow executed often meant looking through multiple files, configurations and database tables. For newer team members, onboarding into the system took time because much of the workflow context was distributed across different parts of the codebase. Even relatively small changes required careful coordination to ensure existing pipelines continued to work as expected. Similarly, debugging typically involved manually tracing logs and rerunning jobs to better understand execution behavior. Limitations of our legacy design We had a monolithic architecture written in Clojure that bundled all our event pipelines together, added dependencies between them and triggered a Lambda function. Legacy Workflow This Lambda function added a single monolithic step to the EMR cluster. If there was an issue in any one of the pipelines, the entire flow would fail due to the single step on the cluster. We did not have step-wise monitoring in the old design, so during on-call situations it became very difficult to identify which part of the pipeline was causing the issue. Photo by Tim Gouw on Unsplash There was no single place to answer basic questions like: What runs first? What happens if this step fails? How do I re-run just one part safely? The scheduler worked, but it was hard to understand, hard to maintain and even harder to explain. That's when we realized we needed a better way. What we actually needed Our aim was less about fancy scheduling features and more about making our daily work easier and more reliable. Simpler onboarding, less mental overhead Our existing step scheduler was built in Clojure and c

## Gemma 3 AI model in Clojure

DevFeed: [Gemma 3 AI model in Clojure](<https://devfeed.tech/articles/gemma-3-ai-model-in-clojure-20729.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/25/Gemma-3-AI-model-in-Clojure>)

Published: 2025-12-09T22:35:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [Inference](<https://devfeed.tech/topics/inference.md>), [Large Language Model](<https://devfeed.tech/topics/llm.md>), [onnx](<https://devfeed.tech/topics/onnx.md>), [gemma](<https://devfeed.tech/topics/gemma.md>)

Tags: [3](<https://devfeed.tech/tags/3.md>), [ai](<https://devfeed.tech/tags/ai.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [deep](<https://devfeed.tech/tags/deep.md>), [diamond](<https://devfeed.tech/tags/diamond.md>), [gemma](<https://devfeed.tech/tags/gemma.md>), [inference](<https://devfeed.tech/tags/inference.md>), [llms](<https://devfeed.tech/tags/llms.md>), [onnx](<https://devfeed.tech/tags/onnx.md>)

### AI overview

This tutorial demonstrates loading and running a one-step Gemma 3 inference in Clojure through the ONNX runtime integration in Deep Diamond. It configures a smaller one-billion-parameter model, uses main-memory tensors with the oneDNN engine, and explains that the demonstrated output is a next-token tensor rather than a complete generated response.

### Source excerpt

Recently I've been working on the ONNX runtime integration into Deep Diamond, backed by the grant sponsored by the Clojurists Together Foundation. In the past few articles, we've seen how ONNX models are integrated into Deep Diamond, using only a single function onnx, with almost no need for additional configuration (which is available). I used a simple MNIST model in the demonstration. But, can we now load and run the inference on the real deal models, such as the open LLMs from the Hugging Face, for example? Let's see! The Hugging Face model card has this to say about Gemma 3: "Gemma is a family of lightweight, state-of-the-art open models from Google, built from the same research and technology used to create the Gemini models." (etc., etc.) So, it seems to be something worth trying. I'll try to be brief, and skip the unnecessary talk. Let's just show the code, which I've just lifted up and adapted from the Diamond's midje tests. What we need for this? First, decide on the backend engine; this time we'll use tensors in main memory backed up by the oneDNN engine (DNNL). (def fact (dnnl-factory)) (def neand-fact (neanderthal-factory fact)) Next, load and configure a particular flavor of Gemma 3 (a smaller one, only 1 billion parameters). The onnx function creates a generalized blueprint, which can create the actual functions when evaluated with the specific input tensors. (def onnx-bp (onnx fact "data/gemma-3-1b-it-ONNX-GQA/onnx/model.onnx" {:options (-> (options) (override-dimension! "batch_size" 1) (override-dimension! "sequence_length" 1) (override-dimension! "past_sequence_length" 1) (override-dimension! "total_sequence_length" 1))}) Gemma 3 has 63 inputs and 61 outputs. We'll need to provide these, but even here we can automate some parts with Clojure, since past-key values are pretty uniform. We only need to provide inputs, while the engine can create the outputs for us. (def src-tz (tensor fact [1 1 28 28] :float :nchw)) (def input-ids (tensor neand-fact [1

## Introducing the Temporal Constellation Program

DevFeed: [Introducing the Temporal Constellation Program](<https://devfeed.tech/articles/introducing-the-temporal-constellation-program-35895.md>)

Original publisher: [Read original article](<https://temporal.io/blog/introducing-the-temporal-constellation-program>)

Author: Kara Deloss

Published: 2025-12-02T00:00:00Z

Content type: release

Language: en

Sources: [Temporal Blog](<https://devfeed.tech/sources/temporal-blog.md>)

Topics: [Automation](<https://devfeed.tech/topics/automation.md>), [Development](<https://devfeed.tech/topics/development.md>), [distributed-systems](<https://devfeed.tech/topics/distributed-systems.md>), [Streaming](<https://devfeed.tech/topics/streaming.md>), [Kafka](<https://devfeed.tech/topics/kafka.md>), [migration](<https://devfeed.tech/topics/migration.md>), [Kubernetes](<https://devfeed.tech/topics/kubernetes.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Go Language](<https://devfeed.tech/topics/go-language.md>), [C#](<https://devfeed.tech/topics/csharp.md>), [SDKs](<https://devfeed.tech/topics/sdks.md>)

Tags: [addition](<https://devfeed.tech/tags/addition.md>), [c-sharp](<https://devfeed.tech/tags/c-sharp.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [community](<https://devfeed.tech/tags/community.md>), [developers](<https://devfeed.tech/tags/developers.md>), [development](<https://devfeed.tech/tags/development.md>), [distributed-systems](<https://devfeed.tech/tags/distributed-systems.md>), [go](<https://devfeed.tech/tags/go.md>), [introduced](<https://devfeed.tech/tags/introduced.md>), [kafka](<https://devfeed.tech/tags/kafka.md>), [kubernetes](<https://devfeed.tech/tags/kubernetes.md>), [orchestration](<https://devfeed.tech/tags/orchestration.md>)

### AI overview

Temporal launches the Constellation Program to recognize and support engineers who have contributed to its ecosystem through code, talks, articles, and community support. The article introduces the first cohort and highlights their work with Temporal across distributed systems, networking, AI and data platforms, Kafka migration, Kubernetes, and SDK development.

### Source excerpt

We've launched the Temporal Constellation Program to recognize all the amazing developers that shape Temporal.

## Plan for Clojure AI, ML, and high-performance Uncomplicate ecosystem in 2026

DevFeed: [Plan for Clojure AI, ML, and high-performance Uncomplicate ecosystem in 2026](<https://devfeed.tech/articles/plan-for-clojure-ai-ml-and-high-performance-uncomplicate-ecosystem-in-2026-20726.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/25/Clojure-AI-ML-high-performance-Uncomplicate>)

Published: 2025-11-29T00:41:00Z

Content type: opinion

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [Machine learning](<https://devfeed.tech/topics/machine-learning.md>), [CUDA](<https://devfeed.tech/topics/cuda.md>), [OpenCL](<https://devfeed.tech/topics/opencl.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [NumPy](<https://devfeed.tech/topics/numpy.md>)

Tags: [2026](<https://devfeed.tech/tags/2026.md>), [ai](<https://devfeed.tech/tags/ai.md>), [ai-ml](<https://devfeed.tech/tags/ai-ml.md>), [algebra](<https://devfeed.tech/tags/algebra.md>), [apple](<https://devfeed.tech/tags/apple.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [cuda](<https://devfeed.tech/tags/cuda.md>), [linear](<https://devfeed.tech/tags/linear.md>), [matrices](<https://devfeed.tech/tags/matrices.md>), [neanderthal](<https://devfeed.tech/tags/neanderthal.md>), [opencl](<https://devfeed.tech/tags/opencl.md>), [programming](<https://devfeed.tech/tags/programming.md>), [vectors](<https://devfeed.tech/tags/vectors.md>)

### AI overview

The article outlines a 2026 development and funding plan for the Uncomplicate ecosystem of Clojure libraries for AI, machine learning, and high-performance computing. It describes support for Nvidia GPUs, Apple Silicon, CPUs, CUDA, OpenCL, and several planned library improvements.

### Source excerpt

I've applied for Clojurists Together yearly funding in 2026. Here's my application. If you are a Clojurists Together member, and would like to see continued development in this area, your vote can help me keep working on this :) My goal with this funding in 2026 is to continuously develop Clojure AI, ML, and high-performance ecosystem of Uncomplicate libraries (Neanderhal and many more), on Nvidia GPUs, Apple Silicon, and traditional PC. In this year, I will also focus on writing tutorals on my blog and creating websites for the projects involved, which is something that I wanted for years, but didn't have time to do because I spent all time on programming. How that work will benefit the Clojure community This will highly benefit the Clojure community as this is THE AI ecosystem for Clojure, and supporting AI is arguably the main focus on probably all software platforms. Clojure has something to offer on that front, beyond just calling OpenAI API as a web service! Uncomplicate grew to quite a few libraries (of which some are quite big; just Neanderthal is 28,000 lines of highly-condensed, aggresively macroized, and reusable code): Diamond ONNX Runtime, Neanderthal, Deep Diamond, ClojureCUDA, ClojureCPP, Apple Presets, ClojureCL, Fluokitten, Bayadera, Clojure Sound, and Commons. Here's a word or two of how I hope to improve each of these libraries with Clojurists Together funding in 2026. Neanderthal (Clojure's alternative to NumPy, on steroids) In 2025, Neanderthal celebrated its 10th birthday. It started as a humble but fast matrix and vector library for Clojure, but after 10 years of relentless improvements, now it boasts a general matrix/vector/linear algebra API implemented by no less than 5(!) engines for CPUs, GPU (Nvidia CUDA), GPU (OpenCL: AMD, Intel, Nvidia), Apple Silicon (Accelerate), and general CPU (OpenBLAS). And this is not a superficial support for the sake of ticking a check box; each of these engines support much more operations on exotic structure

## Writing MCP servers in Clojure with Ring and Malli

DevFeed: [Writing MCP servers in Clojure with Ring and Malli](<https://devfeed.tech/articles/writing-mcp-servers-in-clojure-with-ring-and-malli-29189.md>)

Original publisher: [Read original article](<https://www.latacora.com/blog/2025/11/10/mcp-sdk/>)

Published: 2025-11-10T15:00:00Z

Content type: tutorial

Language: en

Sources: [Latacora](<https://devfeed.tech/sources/latacora.md>)

Topics: [MCP Server](<https://devfeed.tech/topics/mcp-server.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Model Context Protocol](<https://devfeed.tech/topics/model-context-protocol.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [Large Language Model](<https://devfeed.tech/topics/llm.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [databases](<https://devfeed.tech/tags/databases.md>), [language-models](<https://devfeed.tech/tags/language-models.md>), [mcp](<https://devfeed.tech/tags/mcp.md>), [mcp-server](<https://devfeed.tech/tags/mcp-server.md>), [model-context-protocol](<https://devfeed.tech/tags/model-context-protocol.md>)

### AI overview

This tutorial explains how Latacora built a compliant Model Context Protocol server for Clojure applications using Ring and the official Model Context Protocol Java SDK. It presents an open-source Clojure library for exposing Datomic database queries to LLM agents through MCP.

### Source excerpt

Introduction # Large language models, agents, and Model Context Protocol (MCP) are impossible to escape in today's tech climate. At Latacora, we take a thoughtful and pragmatic approach towards new technologies like these. Are they going to solve all the world's problems? No. Is it important that we understand them and be able to build software that integrates into emerging ecosystems? Yes! Internally we've built a MCP server to query our Datomic databases using natural language, but now we're open sourcing the underlying Clojure library so others can easily build robust MCP servers for the emerging LLM agent ecosystem too.

## Four ways to run ONNX models on a GPU with CUDA in Clojure

DevFeed: [Four ways to run ONNX models on a GPU with CUDA in Clojure](<https://devfeed.tech/articles/not-one-not-two-not-even-three-but-four-ways-to-run-an-onnx-ai-model-on-gpu-with-cuda-20728.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/25/Four-Ways-to-ONNX-on-GPU-in-Clojure-and-CUDA>)

Published: 2025-11-09T17:49:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [CUDA](<https://devfeed.tech/topics/cuda.md>), [GPU](<https://devfeed.tech/topics/gpu.md>), [onnx](<https://devfeed.tech/topics/onnx.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Artificial Intelligence](<https://devfeed.tech/topics/ai.md>), [Deep neural networks](<https://devfeed.tech/topics/deep-neural-networks.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [cuda](<https://devfeed.tech/tags/cuda.md>), [deep](<https://devfeed.tech/tags/deep.md>), [diamond](<https://devfeed.tech/tags/diamond.md>), [examples](<https://devfeed.tech/tags/examples.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [image-recognition](<https://devfeed.tech/tags/image-recognition.md>), [model](<https://devfeed.tech/tags/model.md>), [neural-networks](<https://devfeed.tech/tags/neural-networks.md>), [onnx](<https://devfeed.tech/tags/onnx.md>), [tensors](<https://devfeed.tech/tags/tensors.md>)

### AI overview

A tutorial presents four ways to run ONNX models on a GPU with CUDA using Clojure libraries including Diamond ONNX RT, Deep Diamond, and ClojureCUDA. It covers GPU tensor backends and a configuration that keeps input and output tensors in main memory while executing the model on the GPU.

### Source excerpt

Two weeks ago, I announced a new Clojure ML library, Diamond ONNX RT, which integrates ONNX Runtime into Deep Diamond. In that post, we explored the classic Hello World example of Neural Networks, MNIST handwritten image recognition, step-by-step. We run that example on the CPU, from main memory. The next logical step is to execute this stuff on the GPU. You'll see that with a little help of ClojureCUDA and Deep Diamond built-in CUDA machinery, this is both easy and simple, requiring almost no effort from a curious Clojure programmer. But don't just trust me; let's fire up your REPL, and we can continue together. Here's how you can evaluate this directly in your REPL (you can use the Hello World that is provided in the ./examples sub-folder of Diamond ONNX RT as a springboard). Require Diamond's namespaces First things first, we refer functions that we're going to use. (require '[uncomplicate.commons.core :refer [with-release]] '[uncomplicate.neanderthal.core :refer [transfer! iamax native]] '[uncomplicate.diamond [tensor :refer [tensor with-diamond]] [dnn :refer [network]] [onnxrt :refer [onnx]]] '[uncomplicate.diamond.internal.dnnl.factory :refer [dnnl-factory]] '[uncomplicate.diamond.internal.cudnn.factory :refer [cudnn-factory]] '[hello-world.native :refer [input-desc input-tz mnist-onnx]]) None of the following ways to run CUDA models has preference, you use the one that best suits your needs. Way one One of the ways to run ONNX models on your GPU is to simply use Deep Diamond's cuDNN factory as the backend for your tensors. Then, the machinery recognizes what you need and proceeds doing everything on the GPU, using the right stream for tensors, Deep Diamond operations, and ONNX Runtime operations. This looks exactly the same as any other Deep Diamond example from this blog or the DLFP book. (with-diamond cudnn-factory [] (with-release [cuda-input-tz (tensor input-desc) mnist (network cuda-input-tz [mnist-onnx]) classify! (mnist cuda-input-tz)] (transfer! input

## Get Ready for Clojure, GPU, and AI in 2026 with CUDA 13.0

DevFeed: [Get Ready for Clojure, GPU, and AI in 2026 with CUDA 13.0](<https://devfeed.tech/articles/get-ready-for-clojure-gpu-and-ai-in-2026-with-cuda-13-0-20730.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/25/Get-Ready-Clojure-GPU-AI-2026-CUDA-13>)

Published: 2025-10-30T16:37:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [CUDA](<https://devfeed.tech/topics/cuda.md>), [GPU](<https://devfeed.tech/topics/gpu.md>), [OpenCL](<https://devfeed.tech/topics/opencl.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [c-plus-plus](<https://devfeed.tech/tags/c-plus-plus.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [coding](<https://devfeed.tech/tags/coding.md>), [cuda](<https://devfeed.tech/tags/cuda.md>), [deep](<https://devfeed.tech/tags/deep.md>), [diamond](<https://devfeed.tech/tags/diamond.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [opencl](<https://devfeed.tech/tags/opencl.md>), [tensors](<https://devfeed.tech/tags/tensors.md>)

### AI overview

The article introduces ClojureCUDA 0.25.0, which supports CUDA 13.0.2, and encourages Clojure developers to try GPU programming interactively through the Clojure REPL. It explains that GPU acceleration is most useful for large vectors and sufficiently complex workloads because data transfer costs can outweigh computation gains.

### Source excerpt

A little anniversary Did you know that CUDA has been available in Clojure for the last 9 years through ClojureCUDA, and GPU programming through OpenCL for more than 10? I almost forgot about these anniversaries. Ten years ago most people liked it a lot, starred it on Github, patted me on the back, but then concluded that they don't have an Nvidia card available on their laptops, or, if they had GPUs, that they won't have time to learn to think in massive parallel algorithms, or if they have time and will, that there are no GPUs in the servers, so what would they do with their applications, even if they created them in Clojure, and so on, and so off :) But, ClojureCUDA and ClojureCL continued living on for these 10 years, I used them in creating Neanderthal, Deep Diamond, and Diamond ML, and they proved themselves as simple and reliable tools. I still had trouble convincing Clojure programmers that they can write GPU programs that run as fast as they'd wrote them in C++, but interactively in the Cloujre REPL, without C++ hell. But I'm not easy to shake off! If it's necessary, I'll continue for 10 more years, for I'm convinced there'd be a moment when Clojure programmers are going to say "hmmm, this is something that we can use and be good at!". CUDA 13 is here! I've recently released ClojureCUDA 0.25.0, with support for the latest CUDA 13.0.2! Why not celebrate that by opening the REPL, and coding your first Hello World application on the GPU? I promise, it won't be a usual GPU carpet of text; this is ClojureCUDA, it follows the Clojure philosophy by being simple and interactive! There's not much sense in wielding a GPU to print out "Hello World". Note that it is also not very useful to work with scalar numbers and call a GPU function to add or multiply two numbers. No. Unless you have many, many, numbers to crunch, stay by your trusty CPU. For our purposes, many, many, numbers would be two vectors of dimension 3 (hey, it's hello world; imagine it's 3 billion). Also,

## Clojure API for Running ONNX Models with ONNX Runtime

DevFeed: [Clojure API for Running ONNX Models with ONNX Runtime](<https://devfeed.tech/articles/clojure-runs-onnx-ai-models-now-join-the-ai-fun-20727.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/25/Clojure-Runs-ONNX-AI-Models-Now>)

Published: 2025-10-26T15:56:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [onnx](<https://devfeed.tech/topics/onnx.md>), [AI Models](<https://devfeed.tech/topics/ai-models.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [deep](<https://devfeed.tech/tags/deep.md>), [diamond](<https://devfeed.tech/tags/diamond.md>), [onnx](<https://devfeed.tech/tags/onnx.md>), [tensors](<https://devfeed.tech/tags/tensors.md>)

### AI overview

The author describes work on a Clojure API for using pre-trained models exported in ONNX format through ONNX Runtime. The approach uses ONNX Runtime's underlying C library rather than Python interoperability.

### Source excerpt

Hello, Clojurians! I haven't written here in a long time. Was I tired? Is anybody reading blogs anymore? Who knows. But that was not the main reason. I've been working on several Clojure projects sponsored by the Clojurists Together Foundation. I did a ton of things, but after all this programming, I was kinda tired, and kept slugging when it comes to telling people about the work done! That's not very smart, but you know how it goes... :) But, then, if we don't tell people about awesome software that we have, nobody is going to use it, so finally I had to stop kicking this down the road, sit, and write the first post. It's been long overdue, so expect more posts soon! ONNX Runtime in one line of Clojure The most recent thing I'm currently working on started its life as Clojure ML (again, superthanks to Clojurists Together for sponsoring this). I proposed to create a human-friendly Clojure API for AI/DL/ML models, and back it by the first implementation, in this case based on ONNX Runtime. Of course, it should all be integrated into existing Clojure libraries, and follow the Clojure way of doing stuff as much as possible! The idea is to get an existing, pre-trained ML model previously exported to the ONNX format from whatever technology the authors chose (which in today's world is typically Python and PyTorch), and put it into production in Clojure and JVM. It should be seamless and in-process, without any clunky interoperability, copy, translation, etc. Of course, our Clojure numerical libraries fully support GPU computing, so it goes without saying that we want that, too! Just to be clear, we do not use nor need any Python or Python interop for this, we use the ONNX Runtime's underlying C library. Nice idea, but what parts of this well intended story can we evaluate in our REPLs right now? At least some promising demo? Are we on the trail? To access that AI goodness, we surely have to do a sophisticated dance? Are the steps hard to learn? Do we need to watch careful

## Using Clojure channels to increase throughput

DevFeed: [Using Clojure channels to increase throughput](<https://devfeed.tech/articles/using-clojure-channels-to-increase-throughput-30521.md>)

Original publisher: [Read original article](<https://medium.com/helpshift-engineering/using-clojure-channels-to-increase-throughput-c051cc7f9893?source=rss----3229f31ca4f4---4>)

Author: Abhinav Dubey

Published: 2025-05-28T10:07:12Z

Content type: tutorial

Language: en

Sources: [Helpshift](<https://devfeed.tech/sources/helpshift.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>), [Kafka](<https://devfeed.tech/topics/kafka.md>), [benchmarking](<https://devfeed.tech/topics/benchmarking.md>), [async](<https://devfeed.tech/topics/async.md>), [Grafana](<https://devfeed.tech/topics/grafana.md>)

Tags: [benchmarking](<https://devfeed.tech/tags/benchmarking.md>), [channel](<https://devfeed.tech/tags/channel.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [concurrency](<https://devfeed.tech/tags/concurrency.md>), [core-async](<https://devfeed.tech/tags/core-async.md>), [grafana](<https://devfeed.tech/tags/grafana.md>), [kafka](<https://devfeed.tech/tags/kafka.md>), [multithreading](<https://devfeed.tech/tags/multithreading.md>), [parallelism](<https://devfeed.tech/tags/parallelism.md>)

### AI overview

This tutorial explains how to increase throughput in a Clojure-based Kafka consumer by using core.async channels and multiple worker threads. It compares a single-threaded baseline with configurations using three and ten workers, reporting shorter processing times for 1,000 events in the described benchmark.

### Source excerpt

When building systems that process large volumes of messages synchronously, performance bottlenecks can quickly become a challenge specially with single-threaded designs. In this post, we'll look at how leveraging worker threads in a Clojure-based Kafka consumer can significantly boost throughput & reduce total processing time. Using simple concurrency primitives, it's possible to achieve parallelism & scale gracefully, all while keeping the codebase clean & maintainable. We'll start with a baseline, introduce worker threads using Clojure's core.async & measure the impact. Setup & Context Kafka & Zookeeper For observability: Grafana Kafka producer: A simple script that sends messages to a Kafka topic at a configurable rate (messages per minute) for a fixed duration. After each event is pushed, a counter metric is emitted Kafka consumer: A simple script that listens to a topic & consumes messages & simulates processing time finding square-root of a number (henceforth, assume that it takes ~1 second to find the square root) . A counter metric is emitted after processing each message The Baseline: Single-Threaded Consumer If each message takes t seconds to process & there are n messages, total processing time becomes n x t seconds. This provides a clean baseline to evaluate the impact of using channel moving forward. Adding workers with core.asyncValues are conveyed on queue-like channels. By default channels require producer and consumer to rendezvous for the transfer of a value through the channel https://clojuredocs.org/clojure.core.async To improve throughput, we introduce parallelism using Clojure's core.async channels. Messages from Kafka are fed into a channel, & multiple worker threads read from this channel to process messages concurrently Here, we used >!! (blocking put) & <!! (blocking take) to communicate via channels & future to execute the business-logic on a separate thread Who gets blocked & when : The thread putting message into the channel will get bl

## Datomic and Datalog for Complex Data Queries

DevFeed: [Datomic and Datalog for Complex Data Queries](<https://devfeed.tech/articles/datomic-and-content-addressable-techniques-an-ultimate-data-wonderland-29182.md>)

Original publisher: [Read original article](<https://www.latacora.com/blog/2024/09/13/datomic-and-content-addressable-techniques/>)

Published: 2024-09-13T17:00:00Z

Content type: article

Language: en

Sources: [Latacora](<https://devfeed.tech/sources/latacora.md>)

Topics: [Databases](<https://devfeed.tech/topics/databases.md>), [data](<https://devfeed.tech/topics/data.md>), [Security](<https://devfeed.tech/topics/security.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Amazon S3](<https://devfeed.tech/topics/amazon-s3.md>)

Tags: [analysis](<https://devfeed.tech/tags/analysis.md>), [aws](<https://devfeed.tech/tags/aws.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [data](<https://devfeed.tech/tags/data.md>), [database](<https://devfeed.tech/tags/database.md>), [programming](<https://devfeed.tech/tags/programming.md>), [s3](<https://devfeed.tech/tags/s3.md>), [security](<https://devfeed.tech/tags/security.md>)

### AI overview

Latacora describes moving from service-configuration snapshots stored in Amazon S3 toward Datomic, whose immutable facts and Datalog queries support complex questions across security data and relationships between resources.

### Source excerpt

Latacora collects and analyzes data about services our clients use. You may have read about our approach to building security tooling, but the tl;dr is we make requests to all the (configuration metadata) read-only APIs available to us and store the results in S3. We leverage the data to understand our clients' infrastructure and identify security issues and misconfigurations. We retain the files ("snapshots") to support future IR/forensics efforts. This approach has served us well, but the limited scope of a snapshot meant there was always a problem of first needing to figure out which files to look at. We love aws s3 sync and grep as much as anyone but security analysis requires looking for complex relationships between resources; text search is, at best, only a Bloom filter. What we really wanted was a performant way to ask any question across all the data we have for a client that would support complex queries using logic programming.

## Functional Classes in Clojure

DevFeed: [Functional Classes in Clojure](<https://devfeed.tech/articles/functional-classes-in-clojure-21800.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2023/01/19/functional-classes-clojure.html>)

Published: 2023-01-19T00:00:00Z

Content type: article

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Functional programming](<https://devfeed.tech/topics/functional-programming.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Code](<https://devfeed.tech/topics/code.md>), [Polymorphism](<https://devfeed.tech/topics/polymorphism.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [functional-programming](<https://devfeed.tech/tags/functional-programming.md>), [inheritance](<https://devfeed.tech/tags/inheritance.md>), [programming](<https://devfeed.tech/tags/programming.md>)

### AI overview

The article explains how class-like abstractions can be implemented in functional programming using Clojure. It presents a Dilithium Cloud example built from named functions, an internally defined data structure, dynamic type specifications, constructors, methods, and unit-test validation, while arguing that class syntax, inheritance, and polymorphic dispatch are not required.

### Source excerpt

My previous blog seemed only to continue the confusion regarding classes in Functional Programming. Indeed, many people got quite irate. So perhaps a bit of code will help. Trigger Warning: Object Oriented Terminology. Dynamically Typed Language. Mixed Metaphors. Distracting Animations. To all the adherents of the Statically Typed Functional Programming religion: I know that you believe that Static Typing is an essential aspect of Functional Programming and that no mere dynamically typed language could ever begin to approach the heights and glory of The One True and Holy TYPED Functional Apotheotic Paradigm. But we lowly programmers quivering down here at the base of Orthanc can only hope to meekly subsist on the dregs that fall from on high. (R.I.P. Kirstie Alley OK, so, once again... A class is an intentionally named abstraction that consists of a set of narrowly cohesive functions that operate over an internally defined data structure. We do not need the class keyword. Nor do we need polymorphic dispatch. Nor do we need inheritance. A class is just a description, whether in full or in part, of an object. For example - it's time we talked about clouds (which I have looked at from both sides now; and do, in fact, understand pretty well). So... Here come your father's parentheses! (ns spacewar.game-logic.clouds (:require [clojure.spec.alpha :as s] [spacewar.geometry :as geo] [spacewar.game-logic.config :as glc])) (s/def ::x number?) (s/def ::y number?) (s/def ::concentration number?) (s/def ::cloud (s/keys :req-un [::x ::y ::concentration])) (s/def ::clouds (s/coll-of ::cloud)) (defn valid-cloud? [cloud] (let [valid (s/valid? ::cloud cloud)] (when (not valid) (println (s/explain-str ::cloud cloud))) valid)) (defn make-cloud ([] (make-cloud 0 0 0)) ([x y concentration] {:x x :y y :concentration concentration})) (defn harvest-dilithium [ms ship cloud] (let [ship-pos [(:x ship) (:y ship)] cloud-pos [(:x cloud) (:y cloud)]] (if (< (geo/distance ship-pos cloud-pos) glc/dilit

## Recurrent Networks Hello World in Clojure with new Deep Diamond RNN support on CPU and GPU

DevFeed: [Recurrent Networks Hello World in Clojure with new Deep Diamond RNN support on CPU and GPU](<https://devfeed.tech/articles/recurrent-networks-hello-world-in-clojure-with-new-deep-diamond-rnn-support-on-cpu-and-gpu-20724.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/22/Recurrent-networks-hello-world-sequence-prediction-in-Clojure-with-new-Deep-Diamond>)

Published: 2022-08-26T14:25:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Deep learning](<https://devfeed.tech/topics/deep-learning.md>), [Time Series](<https://devfeed.tech/topics/time-series.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [cpu](<https://devfeed.tech/tags/cpu.md>), [deep](<https://devfeed.tech/tags/deep.md>), [deep-learning](<https://devfeed.tech/tags/deep-learning.md>), [diamond](<https://devfeed.tech/tags/diamond.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [learning](<https://devfeed.tech/tags/learning.md>), [networks](<https://devfeed.tech/tags/networks.md>), [neural](<https://devfeed.tech/tags/neural.md>), [programming](<https://devfeed.tech/tags/programming.md>), [recurrent](<https://devfeed.tech/tags/recurrent.md>), [rnn](<https://devfeed.tech/tags/rnn.md>), [time-series](<https://devfeed.tech/tags/time-series.md>)

### AI overview

A beginner-friendly Clojure tutorial demonstrates recurrent neural networks in Deep Diamond by training a model to predict the next value in a simple numerical sequence. It introduces time-series prediction and notes that the example can run on CPU and GPU.

### Source excerpt

I've been busy in the last period working on new major features in Deep Diamond, one of which is the support for Recurrent Neural Networks (RNN). It's not been an easy ride, but I can finally show you some results! Big thanks for everyone that's helping me with this by buying my books (or subscribing to the upcoming editions), and Clojurists Together, who generously funded me in the past year to work on this. I know that most of you probably don't have much more than passing familiarity with deep learning, let alone recurrent neural networks, and that's why I'll try to show a very simple example on the level of Hello World that anyone interested in machine learning and programming can understand and try. So, enough talk, let's get down to business. What are we doing We are demonstrating a hammer: recurrent neural networks. Just kidding; we would like to create a (software) device that can learn to predict the next data point in a series. Depending on the data, this can be done in a number of ways (even by convolutional neural networks (CNN) that Deep Diamond already supported), one of which is RNN. So, we are creating a recurrent network, and training it with a set of data for this task. An example of data that fits this task would be temperature at some place, stock prices, and any other (possibly infinite) sequence of numbers in one of more dimensions that have an ordinal relation, that is, has an abstract notion of time attached to it. Then, we are trying to forecast one or more values that are happening in the future (temperature the next day, or the closing price of a stock, etc.). Since Hello World has to be dead simple, a real example would have too many opaque numbers, so we'll solve an artificially trivial task of teaching our network to predict the next number in the series for obvious series such as 1, 2, 3, 4, 5. Of course, in real life we rarely need to solve that exact task with such a bazooka as RNN, but if this is your first contact with time series

## Clojure Sound - 5 - Double Click with Foot Control

DevFeed: [Clojure Sound - 5 - Double Click with Foot Control](<https://devfeed.tech/articles/clojure-sound-5-double-click-with-foot-control-20723.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/22/Clojure-Sound-5-Double-Click-with-Foot-Control>)

Published: 2022-07-30T15:45:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [MIDI](<https://devfeed.tech/topics/midi.md>), [Playback](<https://devfeed.tech/topics/playback.md>), [ui](<https://devfeed.tech/topics/ui.md>)

Tags: [audio](<https://devfeed.tech/tags/audio.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [desktop](<https://devfeed.tech/tags/desktop.md>), [interface](<https://devfeed.tech/tags/interface.md>), [music](<https://devfeed.tech/tags/music.md>), [playback](<https://devfeed.tech/tags/playback.md>), [sound](<https://devfeed.tech/tags/sound.md>), [user-interface](<https://devfeed.tech/tags/user-interface.md>)

### AI overview

This article discusses designing foot-controller gestures for a Clojure audio player. It examines button press, release, and double-click signals, and describes how those signals could control clip playback and address the need to rewind tracks.

### Source excerpt

In the last article we created a receiver function that listened to signals from our foot controller and started or stopped playback on consecutive clicks. The trouble with our player it that it only works until the end of the track. The start! function does not automatically rewind the playback. Neither stop! does that. Our program is responsible for detecting that the track should be rewound, perhaps by detecting that we reached the end of track (but even that is not fool proof, since audio infrastructure is not that precise). Now we have to think about a foot user interface that is useful and simple at the same time - there's not many different precise actions that a foot can do. My idea at this time is the following: distinguish three gestures: Button (un)pressed (value 0) Button pressed (value 127) Button pressed twice in a short time span (doubleclick). This can have two varieties: First pressed (value 127), then (un)pressed (value 0) (Un)pressed (value 0), then pressed (value 127). The values 0 and 127 always interchange, there's no way to send the same value twice in a row (with the MIDI controller I have). This gives us 4 different signals from one button that we can work with, which doesn't seem that much, but on the other hand, we can't assume that the feet of our user that is doing all this stomping is able or eager for much more complicated stuff. So, if I assume that the particular button is dedicated to a particular clip playback, I see the following actions: If the button is (un)pressed (value 0), the clip should stop, regardless of the previous state. If the clip has not been playing, nothing changes. If the button is pressed (value 127), the clip should start, regardless of the previous state. If the clip has been playing, it just keeps playing. If the button is clicked twice in a row, the things might get complicated! It's not exactly rocket science level complicated, but we still need to think what to do. In our desktop user interface toolkits, w

## Clojure Sound - 4 - Ctrl-Left-Pedal

DevFeed: [Clojure Sound - 4 - Ctrl-Left-Pedal](<https://devfeed.tech/articles/clojure-sound-4-ctrl-left-pedal-20722.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/22/Clojure-Sound-4-Ctrl-Left-Pedal>)

Published: 2022-07-13T18:45:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [MIDI](<https://devfeed.tech/topics/midi.md>)

Tags: [article](<https://devfeed.tech/tags/article.md>), [audio](<https://devfeed.tech/tags/audio.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [debug](<https://devfeed.tech/tags/debug.md>), [devices](<https://devfeed.tech/tags/devices.md>), [how-to](<https://devfeed.tech/tags/how-to.md>), [music](<https://devfeed.tech/tags/music.md>), [play](<https://devfeed.tech/tags/play.md>), [sound](<https://devfeed.tech/tags/sound.md>), [usb](<https://devfeed.tech/tags/usb.md>)

### AI overview

This article explores using Clojure to build a basic audio player controlled by MIDI input. It describes playing selected segments of a WAV recording with arbitrary repetitions and connecting both a USB MIDI controller and a MIDI-connected foot pedal.

### Source excerpt

In the last article we managed to connect a MIDI controller and receive updates whenever something happens to its knobs and buttons. So what? As it is, nothing. Printing out messages is not of much use, beyond perhaps getting informed about how these messages look like, and what kind of data they typically contain. On another thought, exactly that is often valuable, because how else can we debug what's happening and learn how to use these devices. They typically don't come with terrific manuals. Luckily, basic use revolves around receiving one of a few kind of standard messages, that typically contain only a handful of bytes, more or less conforming to the MIDI standard, so it's up to us to assign the meaning according to our use case. If we care to read the standard, we could try to pick the closest meaning in our application, but if that's not possible, or practical, well... you live only once. Let's celebrate creativity and be silly. What I would like Cool, so, at first, I have an audio recording of a few chords interposed with some talk and noise, just a single wav file. I'd like to discover how to play only selected segments (i.e. the chords I'm interested in guessing), with arbitrary repetitions. The purpose of this is not to create a perfect looper or learning device, at least not yet. At first, I'm just interested in creating the crudest audio player, and discovering how to connect the player to react to the input from the MIDI controller that we connected last week. After that, it would be nice to see whether the foot pedal works in the same way, or it needs more poking. As we discovered last week, the more modern Faderfox MX12 connects through USB and is listed as one of the connected MIDI devices. The Roland FC-300 foot pedal, does not support USB, so I connect it via a 5-pin MIDI cable to my USB sound card. It will probably be displayed as a MIDI in/out of that sound card (more on that later). MIDI Controller (hands) The usual imports: (ns my-midi) (requir

## Clojure Sound 3 - Hello MIDI Controller

DevFeed: [Clojure Sound 3 - Hello MIDI Controller](<https://devfeed.tech/articles/clojure-sound-3-hello-midi-controller-20721.md>)

Original publisher: [Read original article](<http://dragan.rocks/articles/22/Clojure-Sound-3-Hello-MIDI-Controller>)

Published: 2022-06-30T21:59:00Z

Content type: tutorial

Language: en

Sources: [Dragan Djuric](<https://devfeed.tech/sources/dragan-djuric.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [MIDI](<https://devfeed.tech/topics/midi.md>), [Arch Linux](<https://devfeed.tech/topics/archlinux.md>), [Linux](<https://devfeed.tech/topics/linux.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [connectivity](<https://devfeed.tech/tags/connectivity.md>), [core](<https://devfeed.tech/tags/core.md>), [music](<https://devfeed.tech/tags/music.md>), [sound](<https://devfeed.tech/tags/sound.md>), [tutorial](<https://devfeed.tech/tags/tutorial.md>), [usb](<https://devfeed.tech/tags/usb.md>)

### AI overview

A Clojure Sound tutorial that introduces MIDI controller input and explains how to use it to control software on a computer. It discusses MIDI device connectivity, Clojure Sound, and example hardware such as the Faderfox MX12.

### Source excerpt

You may not know that music instrument were connected devices even in the Stone Age, that is, many decades ago. In the 80's that even resulted in the standard that facilitated connectivity of heterogeneous devices. Typically, you'd have a keyboard, a synthesizer, some external knobs, maybe effect boxes, and many of them could be connected by cable and talk to each other, even though that synth might be 27 years old, and the keyboard 2 years old. That's the power of standard. MIDI might not be technically impressive. Especially for 2022, its transfer rate is unbelievably slow. On the other hand, a random device that you'd pick up at the store, on a yard sale, e-bay, or even at the dumpster, is almost guaranteed to have a MIDI connector. So, even though you'd have a hard time connecting your iPhone with your Linux laptop, my guitar can talk with my Arch Linux desktop just fine (I'm not kidding, it really does!). Making that guitar send a meaningful data to my computer is another pair of shoes. MIDI is very basic, and it's up to the user program to make sense of the data it receives. It is likely that you'll want to use a random exotic device in a very specific way; after all, music and art are all about originality. But, to walk on the Moon, we first have to get up from our bed. That's today's objective: taking input from a MIDI device, and controlling something on our computer by twisting knobs. The software As for the software, we need nothing more than Clojure Sound(), of course! You can read how to prepare a fairly basic Clojure project in the first article in Clojure Sound tutorial series. (require '[uncomplicate.commons.core :refer [close! info]] '[uncomplicate.clojure-sound [core :refer :all] [midi :refer :all] [sampled :refer :all]]) The hardware It is unlikely that you'll have the same controller that I do, but so what? Any MIDI device that has a button or a knob on it will do! At this moment, I'm using Faderfox MX12, not because it's a great device (which it

## Space War

DevFeed: [Space War](<https://devfeed.tech/articles/space-war-21798.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2021/11/28/Spacewar.html>)

Published: 2021-11-28T00:00:00Z

Content type: article

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Functional programming](<https://devfeed.tech/topics/functional-programming.md>), [GUI](<https://devfeed.tech/topics/gui.md>), [Code](<https://devfeed.tech/topics/code.md>), [Framework](<https://devfeed.tech/topics/framework.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [blog](<https://devfeed.tech/tags/blog.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [functional-programming](<https://devfeed.tech/tags/functional-programming.md>), [gui](<https://devfeed.tech/tags/gui.md>), [programming](<https://devfeed.tech/tags/programming.md>), [project](<https://devfeed.tech/tags/project.md>), [space](<https://devfeed.tech/tags/space.md>)

### AI overview

The article describes the author's return to Space War, a game first written in 1978 and revisited in a newer version started in 2018. The newer system is an animated, GUI-driven application written entirely in Clojure, using Quil as a shim for the Processing GUI framework. The author discusses how functional design, organization, and extensive tests made the codebase easy to understand after several years.

### Source excerpt

For the last month I've been spending a lot of time working on Space War. I know, I know, I should have been working on Clean Code Episode 67: Legacy Code, and Euler 5, and Countest and Curmugeon 3. I should have been working on a blog, or a new book, or... But I couldn't let go of Space War. It kept calling me. The first time I wrote Space War was in 1978. I wrote it in Alcom, which was a simple derivative of Focal, which was an analog of Basic for the PDP-8. The computer was an M365 which was an augmented version of a PDP-8 and was proprietery to Teradyne, my employer at the time. The UI was screen based, using character graphics, similar to curses. Screen updates took on the order of a second. All input was through the keyboard. We used to play it on one machine while waiting for a compile on another. Forty years later, in September of 2018, I started working on this version of Space War. It's an animated GUI driven system with a frame rate of 30fps. It is written entirely in Clojure and uses the Quil shim for the Processing GUI framework. My justification for writing it was so that I could use it as the case study for my cleancoders.com videos on Functional Programming. Once that series of videos was complete, I set Space War aside and started working on other things. Then, a month ago, the program called to me. I don't know why. Perhaps it was because I'd left it in a partially completed state. Perhaps it was because I had just finished Clean Craftsmanship and I needed a way to decompress. Or, perhaps it was just because I felt like it. Whatever the reason, I loaded up the project and started goofing around with it. Now I'm sure you've had that feeling of trepidation when you pick up a code base that you haven't seen in three years. I certainly felt it. I mean, what was I going to find in there? Would I be able to get my bearings and understand the code? Or would I flail around aimlessly for weeks? I needn't have worried. The code base was nicely organized. The

## More On Types

DevFeed: [More On Types](<https://devfeed.tech/articles/more-on-types-21795.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2021/06/29/MoreOnTypes.html>)

Published: 2021-06-29T00:00:00Z

Content type: article

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Code](<https://devfeed.tech/topics/code.md>), [Framework](<https://devfeed.tech/topics/framework.md>), [GUI](<https://devfeed.tech/topics/gui.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [framework](<https://devfeed.tech/tags/framework.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [programming](<https://devfeed.tech/tags/programming.md>), [state](<https://devfeed.tech/tags/state.md>), [types](<https://devfeed.tech/tags/types.md>), [velocity](<https://devfeed.tech/tags/velocity.md>)

### AI overview

The article presents a turtle graphics program written in Clojure and explores the type model of its turtle object using clojure/spec. It describes the turtle's geometric and animation-related state, including position, heading, velocity, distance, angular velocity, pen state, and related constraints.

### Source excerpt

Recently I wrote a cute little program for doing Turtle Graphics. For those of you who don't know, turtle graphics were originally added to the LOGO language by Seymour Papert in the late 1960s. He built a robot that he called a "turtle" that could hold a pen. The robot had wheels and could move forwards and backwards, and could rotate left and right. It could also raise and lower the pen. When placed on a sheet of paper, the turtle could be commanded to draw interesting designs. Papert's goal was to teach children about programming. As the years went by the robot got replaced with screens, and the turtle became an icon that could draw lines. Children from the 70s until now have been enthralled by the simple commands for directing the turtle, and the elegant drawings they can make. For example, this is how you might draw a square: forward 100 right 90 forward 100 right 90 forward 100 right 90 forward 100 right 90. Recently I had a need to explore some interesting geometrical designs. Turtle graphics would be perfect for my purposes. So I wrote a turtle graphics processor in Clojure. [code] I used the quil framework which is based on the Processing framework in Java. This framework makes it very easy to create simple GUIs in Clojure. Now consider the problem of the Turtle. What is the type model for this object? What fields does it have, and what constraints must be placed on those fields? Here was my solution to that problem, written in clojure/spec. As usual, in Clojure, you start at the bottom and read towards the top. (s/def ::position (s/tuple number? number?)) (s/def ::heading (s/and number? #(<= 0 % 360))) (s/def ::velocity number?) (s/def ::distance number?) (s/def ::omega number?) (s/def ::angle number?) (s/def ::weight (s/and pos? number?)) (s/def ::state #{:idle :busy}) (s/def ::pen #{:up :down}) (s/def ::pen-start (s/or :nil nil? :pos (s/tuple number? number?))) (s/def ::line-start (s/tuple number? number?)) (s/def ::line-end (s/tuple number? number?)) (s

## Transforming Nested Loops into a Single Loop with State

DevFeed: [Transforming Nested Loops into a Single Loop with State](<https://devfeed.tech/articles/loopy-21790.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2020/09/30/loopy.html>)

Published: 2020-09-30T00:00:00Z

Content type: tutorial

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Code](<https://devfeed.tech/topics/code.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Finite-state machine](<https://devfeed.tech/topics/finite-state-machine.md>), [Algorithms](<https://devfeed.tech/topics/algorithms.md>)

Tags: [algorithm](<https://devfeed.tech/tags/algorithm.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [flow](<https://devfeed.tech/tags/flow.md>), [go](<https://devfeed.tech/tags/go.md>), [i](<https://devfeed.tech/tags/i.md>), [journey](<https://devfeed.tech/tags/journey.md>), [loops](<https://devfeed.tech/tags/loops.md>), [machine](<https://devfeed.tech/tags/machine.md>), [model](<https://devfeed.tech/tags/model.md>), [state](<https://devfeed.tech/tags/state.md>)

### AI overview

This article compares the standard Java solution to the Prime Factors Kata with a Clojure implementation using a single recursive loop. It then shows how nested-loop behavior can be represented with state and transformed into a single loop, culminating in a Moore model finite-state machine.

### Source excerpt

The following is a segment of a journey. It has no obvious beginning point, nor does it actually end up anywhere. The value, if any, is in the journey itself. The code below is the standard solution to the Prime Factors Kata. public List<Integer> factorsOf(int n) { ArrayList<Integer> factors = new ArrayList<>(); for (int d = 2; n > 1; d++) for (; n % d == 0; n /= d) factors.add(d); return factors; } However, I was doing this kata in Clojure the other day and I wound up with a different solution. It looked like this: (defn prime-factors [n] (loop [n n d 2 factors []] (if (> n 1) (if (zero? (mod n d)) (recur (/ n d) d (conj factors d)) (recur n (inc d) factors)) factors))) The algorithm is pretty much the same. I mean if you tracked the value of n, d, and factors they would go through the same changes. On the other hand the code in Java is a doubly nested loop; but the code in Clojure is a single recursive loop with two recursion points. That's interesting. I could write the recursive algorithm in Java like this: private List<Integer> factorsOf(int n) { return factorsOf(n, 2, new ArrayList<Integer>()); } private List<Integer> factorsOf(int n, int d, List<Integer> factors) { if (n>1) { if (n%d == 0) { factors.add(d); return factorsOf(n/d, d, factors); } else { return factorsOf(n, d+1, factors); } } return factors; } And then, since this is tail recursive, I could rewrite it as a straight loop. private List<Integer> factorsOf(int n, int d, List<Integer> factors) { while (true) { if (n > 1) { if (n % d == 0) { factors.add(d); n /= d; } else { d++; } } else return factors; } } For all intents and purposes this code executes the same algorithm as the standard solution; but it does not have a doubly nested loop. We have transformed the code from a doubly nested loop, to a single loop, without affecting the algorithm. Is this always possible? In other words: given a program with a nested loop, is there a way to write the same program with a single loop? The answer to that is

## REPL Driven Design

DevFeed: [REPL Driven Design](<https://devfeed.tech/articles/repl-driven-design-21787.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2020/05/27/ReplDrivenDesign.html>)

Published: 2020-05-27T00:00:00Z

Content type: opinion

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Test-driven development](<https://devfeed.tech/topics/tdd.md>), [Code](<https://devfeed.tech/topics/code.md>), [GitHub](<https://devfeed.tech/topics/github.md>)

Tags: [bug](<https://devfeed.tech/tags/bug.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [coronavirus](<https://devfeed.tech/tags/coronavirus.md>), [data](<https://devfeed.tech/tags/data.md>), [github](<https://devfeed.tech/tags/github.md>), [mocking](<https://devfeed.tech/tags/mocking.md>), [tdd](<https://devfeed.tech/tags/tdd.md>), [tests](<https://devfeed.tech/tags/tests.md>)

### AI overview

The article reflects on using REPL Driven Design while developing a Clojure program that processes daily Coronavirus statistics from the Johns Hopkins GitHub repository. The author found REPL experiments and tests fast and confidence-building, and real production data reduced the need for mocks and fake data. However, a later design change exposed weak verification, delayed the change, and ultimately allowed a bug into production that was discovered four days later.

### Source excerpt

If you follow me on facebook you know that I've been publishing daily CoronaVirus statistics. I generate these statistics using the daily updates in the Johns Hopkins github repository. At first I just hand copied the data into a spreadsheet. But that became tedious quite rapidly. Then, in late March, I wrote a little Clojure program to extract and process the data. Every morning I pull the repo, and then run my little program. It reads the files, does the math, and prints the results. Of course I used TDD to write this little program. But over the last several weeks I've made quite a few small modifications to the program; and it has grown substantially. In making these adaptations I chose to use a different discipline: REPL Driven Design. REPL Driven Design is quite popular in Clojure circles. It's also quite seductive. The idea is that you try some experiments in the REPL to make sure you've got the right ideas. Then you write a function in your code using those idea. Finally, you test that function by invoking it at the REPL. It turns out that this is a very satisfying way to work. The cycle time - the time between a code experiment and the test at the REPL - is nearly as small as TDD. This breeds lots of confidence in the solution. It also seems to save the time needed to mock, and create fake data because, at least in my case, I could use real production data in my REPL tests. So, overall, it felt like I was moving faster than I would have with TDD. But then, in late April, I wanted to do something a little more complicated than usual. It required a design change to my basic structure. And suddenly I found myself full of fear. I had no way to ensure that those design changes wouldn't leave the system broken in some way. If I made those changes, I'd have to examine every output to make sure that none of them had broken. So I postponed the change until I could muster the courage, and set aside the dedicated time it would require. The change was not too painful.

## A Little More Clojure

DevFeed: [A Little More Clojure](<https://devfeed.tech/articles/a-little-more-clojure-21786.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2020/04/09/ALittleMoreClojure.html>)

Published: 2020-04-09T00:00:00Z

Content type: tutorial

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Code](<https://devfeed.tech/topics/code.md>), [Test-driven development](<https://devfeed.tech/topics/tdd.md>), [Java](<https://devfeed.tech/topics/java.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [code](<https://devfeed.tech/tags/code.md>), [how-to](<https://devfeed.tech/tags/how-to.md>), [java](<https://devfeed.tech/tags/java.md>), [libraries](<https://devfeed.tech/tags/libraries.md>), [tdd](<https://devfeed.tech/tags/tdd.md>), [test](<https://devfeed.tech/tags/test.md>)

### AI overview

An introduction to additional Clojure utility functions, including map, filter, range, let, and anonymous functions. The article applies these concepts to finding prime numbers up to one thousand and demonstrates a variant of test-driven development, immutable local bindings, and interoperability with Java libraries.

### Source excerpt

So let's learn just a little bit more of Clojure. Here are a few common utility functions: user=> (inc 1) ; increments argument 2 user=> (dec 3) ; decrements argument 2 user=> (empty? []) ; tests for empty true user=> (empty? [1 2]) false If you know Java or C# you probably know what the map function does. Here's an example: (map inc [1 2 3]) evaluates to (2 3 4). The first argument of map is a function. The second is a list. The map function returns a new list by applying the function to every element of the input list. The filter function also takes a function and a list. (filter odd? [1 2 3 4 5]) evaluates to (1 3 5). From that I think you can tell what both the filter and the odd? functions do. And so with that, let's try a little challenge. Let's find all the prime numbers between one and a thousand. We'll use a variant of TDD to do this. Our eyes will be the tests. The cycle will be the same size as normal TDD; but we'll write a bit of code first and then test it. I know. Blashphemy! So sue me. ;-) We begin like this: (defn primes [n] ) This returns nil. user=> (primes 1000) nil Now let's get all the numbers between 1 and n. (defn primes [n] (range 1 (inc n))) user=> (primes 10) (1 2 3 4 5 6 7 8 9 10) You've probably figured out what range does. It just returns a list of all the integers between it's arguments. OK, so now all we have to do is filter all the primes: (defn primes [n] (let [candidates (range 1 (inc n))] (filter prime? candidates))) CompilerException java.lang.RuntimeException: Unable to resolve symbol: prime? in this context, compiling:(null:3:5) Oh, oh. We need to implement prime? (defn prime? [n]) user=> (primes 10) () OK, that makes sense. But I should explain the let function. It allows you to create names that are bound to expressions. The names exist only within the parentheses of the let expression. So it's a way to create local variables - though the word "variable" is not quite right because they cannot be reassigned. They are immutable.

## A Little Clojure

DevFeed: [A Little Clojure](<https://devfeed.tech/articles/a-little-clojure-21785.md>)

Original publisher: [Read original article](<http://blog.cleancoder.com/uncle-bob/2020/04/06/ALittleClojure.html>)

Published: 2020-04-06T00:00:00Z

Content type: article

Language: en

Sources: [Robert C. Martin](<https://devfeed.tech/sources/robert-c-martin.md>), [The Clean Code Blog](<https://devfeed.tech/sources/the-clean-code-blog.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>)

Tags: [article](<https://devfeed.tech/tags/article.md>), [clojure](<https://devfeed.tech/tags/clojure.md>), [syntax](<https://devfeed.tech/tags/syntax.md>)

### AI overview

An introduction to Clojure covering list syntax, arithmetic and built-in functions, the REPL, quoting, and the implementation of lists as linked lists.

### Source excerpt

So let's learn just a little bit of clojure. This expression: (1 2) represents the list containing the integers 1 and 2 in that order. If you want an empty list, that's just (). And the list of the first five letters of the alphabet is just (\a \b \c \d \e). Now you know a lot about the syntax of clojure. Perhaps you think there's a lot missing. Well, there are a few things missing; but far fewer than you'd think. You might be wondering how you add two numbers. That's easy, that's just (+ 1 2). As it happens that's also just the list of the function named + followed by a 1 and a 2. You see, a function call is really just a list. The function is the first element of the list, and the arguments are just the other elements of that list. When you want to call a function, you simply invoke the list that represents that function call. There are quite a few built-in functions in clojure. For example there's +, -, *, and /. They do precisely what you'd think. Well, perhaps not precisely. (+ 1 2 3) evaluations to 6. (- 3 2 1) evaluates to zero. (* 2 3 4) evaluates to 24. And (/ 20 2 5) evaluates to 2. (- 5) evaluates to -5. (* 5) evaluates to 5. And, get ready for this, (/ 3) evaluates to 1/3. That last is the clojure syntax for the rational number one-third. (first 1 2 3) evaluates to 1, (second 1 2 3) evaluates to 2, and (last 1 2 3) evaluates to - you guessed it - 3. If you'd like to see this in action you'll need to start up a clojure REPL. You can google how to do that. The word REPL stands for Read, Evaluate, Print Loop. It's a very simple program that reads in an expression, evaluates that expression, prints the result of that expression, and then loops back to the read. If you start a REPL you'll get some kind of a prompt, perhaps like this user=>. Then you can type an expression and see it evaluated. Here are a few from my REPL user=> (+ 1 2 3 4) 10 user=> (- 5 6 7 8) -16 user=> (* 6 7 8) 336 user=> (/ 5 6 9) 5/54 If you try the expression at the very start of this

## ICFPC 2019

DevFeed: [ICFPC 2019](<https://devfeed.tech/articles/icfpc-2019-34254.md>)

Original publisher: [Read original article](<https://tonsky.livejournal.com/322258.html>)

Published: 2019-06-27T11:03:26Z

Content type: opinion

Language: ru

Sources: [Tonsky Стой под стрелой](<https://devfeed.tech/sources/tonsky.md>)

Topics: [Clojure](<https://devfeed.tech/topics/clojure.md>), [iteration](<https://devfeed.tech/topics/iteration.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [iteration](<https://devfeed.tech/tags/iteration.md>), [livejournal](<https://devfeed.tech/tags/livejournal.md>), [tag-5e1c061eda96](<https://devfeed.tech/tags/tag-5e1c061eda96.md>), [tag-c40b78a8c8a6](<https://devfeed.tech/tags/tag-c40b78a8c8a6.md>), [tag-d16a2c26554f](<https://devfeed.tech/tags/tag-d16a2c26554f.md>), [tag-e3028c5e0ab2](<https://devfeed.tech/tags/tag-e3028c5e0ab2.md>)

### AI overview

A personal report on participating in ICFPC 2019, a three-day programming competition involving maze-solving with additional equipment. The author describes the team's 29th-place finish among 142 teams, team size considerations, and the perceived performance limitations of Clojure for this challenge.

### Source excerpt

В этот понедельник закончился трехдневный марафон под названием ICFPC. Это такое соревнование, где команды программистов со всего мира пытаются на время как можно лучше решить некую задачу. В этот раз - обход лабиринтов с разным доп. инвентарем. Условия можно прочитать здесь. Это как бы отчет, но на самом деле памятка самому себе на случай, если буду играть еще через год. Мне очень понравилось. То есть я конечно устал как собака, но есть что-то приятное в том что этот опыт а) имеет конечную продолжительность, а не тянется годами, как основная работа. И б) можно полностью отдаться задаче, не думая о том зачем это все и что ты делаешь со своей жизнью. Такой вот повод упоенно фигачить на полной скорости какое-то время, чтобы ветер свистел в ушах. Ну и просто весело. Очень любопытно посмотреть, чего ты стоишь. В голове-то ты мог много себе про себя нафантазировать, а тут вот объективная реальность, ладдер, и ты либо можешь компьютер заставить делать что ты хочешь, либо не можешь. Никаких "если бы", никаких "возможно, наверное, мне кажется". Мы довольно посредственно выступили (на момент закрытия 29 место из 142 участвовавших, в лучший свой момент были на пятом). Исторический скриншот. Дальше мы сильно сдали Участвовали втроем, я в первый раз. Как я понял, средний размер команды ~5 человек, не редкость и восемь встретить. Втроем у нас довольно хорошо делились области ответственности, было бы больше появился бы организационный оверхед (как мне кажется). Восемь человек я бы вообще офигел менеджить и вообще ничего бы не написал, наверное. С другой стороны, больше рук - можно попробовать больше подходов. Можно вложиться в инфрастуктуру. Наверное. Задача достаточно нетривиальная, чтобы решить ее до конца было в принципе невозможно. Но и не супер-сложная, чтобы как-то ее решить можно было бы даже иногда и руками (ну, самые простые примеры). Как правило это значит перебор вариантов в каком-то NP-полном поле, соревнование эвристик. Собери бонусы, закрась лабиринт Clojure, несмот

## Why Small Programming Languages Can Encourage Implementations Instead of Use

DevFeed: [Why Small Programming Languages Can Encourage Implementations Instead of Use](<https://devfeed.tech/articles/the-siren-song-of-little-languages-22023.md>)

Original publisher: [Read original article](<http://www.wilfred.me.uk/blog/2019/03/24/the-siren-song-of-little-languages/>)

Author: Wilfred Hughes

Published: 2019-03-24T00:00:00Z

Content type: opinion

Language: en

Sources: [Wilfred Hughes](<https://devfeed.tech/sources/wilfred-hughes.md>)

Topics: [Programming](<https://devfeed.tech/topics/programming.md>), [Esolang](<https://devfeed.tech/topics/esolang.md>), [Lisp](<https://devfeed.tech/topics/lisp.md>), [Clojure](<https://devfeed.tech/topics/clojure.md>), [Racket](<https://devfeed.tech/topics/racket.md>)

Tags: [clojure](<https://devfeed.tech/tags/clojure.md>), [languages](<https://devfeed.tech/tags/languages.md>), [lisp](<https://devfeed.tech/tags/lisp.md>), [programming](<https://devfeed.tech/tags/programming.md>), [programming-languages](<https://devfeed.tech/tags/programming-languages.md>)

### AI overview

This commentary examines how small, elegant programming-language specifications can encourage developers to build implementations rather than use the language. It discusses BF, Scheme, Shen, Forth, Clojure, and Racket, and argues that language designers should consider the risk while recognizing that multiple implementations can also indicate language health.

### Source excerpt

Some programming languages languish due to obscurity. They lack breathless blog posts exclaiming how much nicer they are to use. Other languages are too ambitious. They aspire to support so many features that the original implementers struggle to get a first version working. For example, the type system in Fortress required constraint solving which took exponential time. Sometimes a usable language struggles simply because it's too much fun to write your own. Developers end up building their own implementation rather than actually using the language. The most obvious implementation-focused language is BF. Despite having many implementations, BF programmers have to encourage the implementers to actually try using the language! Scheme is also susceptible to this. Wikipedia lists 31 different Scheme implementations, not to mention the many toy implementations. Writing a Scheme is a great introduction to interpreters, especially once you get beyond the minimal lisp featureset. I've certainly written more implementation code than Scheme code. The problem seems to be languages with a small, well written specification. Shen is a multiparadigm lisp defined in terms of an elegant base language with only 46 system functions. This has resulted in a remarkable 15 third-party implementations, but only a small number of libraries implemented in the language. This phenomenon is not limited to lisps. Forth is also a language that developers often prefer to implement rather than use. Jones Forth is both a Forth tutorial and a discussion of how to build a Forth compiler. There are even stories of people spending years working on implementations without learning much of the language. Designing a language with a straightforward implementation is not a bad thing. It's just a pitfall that language designers need to be aware of. Some crypto systems have this problem too. It seems that we need languages to be big enough that new users write hello world in the language, not write a tool for

[Next page](<https://devfeed.tech/topics/clojure.md?cursor=WyIyMDE5LTAzLTI0VDAwOjAwOjAwKzAwOjAwIiwgIjMxOTMwODg1LWMyMzUtNGM5Zi05YTY2LWQ5Y2Q0NzFlZmM4MyJd>)