The long way through Software Craftsmanship

The Threading Macro (clojure) equivalent in Python

Jul 22, 2023 - 2 minute read - Comments - equivalencethreading-macroclojurelispmacropythonlanguagelanguage-equivalence

Introduction

In any programming language, it is common to compose functions by pipelining functions: h = g ∘ f such that h(x) = g(f(x)).

The function f is applied first, then g, then the following. 1

For me, it would be more comfortable and easy to understand to write it f COMPOSE_THEN g, indicating that this function composition is not the usual, but a different operation.

Introduction in Clojure

This function composition can be written in Clojure by pipelining or chaining functions:

(defn calculate []
   (reduce + (map #(* % %) (filter odd? (range 10)))))

Fig 1: Example taken from Clojure’s threading macros. Notice the (range 10) is written at the right-most, while the functions are at the left of it.

The threading macros are also a magnificent way to chain or pipeline operations: take a value and put it through the following functions:

(defn calculate* []
   (->> (range 10)
        (filter odd?)
        (map #(* % %))
        (reduce + )))

Fig 2: when using threading macros. Notice the (range 10) is written at the beginning, while the functions are to the right of it. This is a more natural way of reading code (left to right).

Python

In python, I haven’t found any equivalent 2 to these threading macros, but it is possible to create an equivalent 3:

def chain(arg: object, *funcs: Any) -> object:
    return reduce(lambda r, f: f(r), funcs, arg)

and to use it:

chain(range(10),
      lambda ele: filter(lambda x: x % 2 == 1, ele),
      lambda ele: map(lambda x: x * x, ele),
      sum
      )

The upside is that you can now chain functions, while the parameter is at the beginning.

The obvious downside is you need to create lambda functions for each of the functions.


  1. The notation g ∘ f is read as “g of f “, “g after f " (…). From wikipedia: Function Composition ↩︎

  2. In the python 3 SDK or the Standard Library. There might be alternatives, but I haven’t researched them: funcy, funcoperators, or toolz. ↩︎

  3. This Stack Overflow thread is related to function composition ↩︎

Disclaimer about AI/GenAI

As of 2026-05-06, the text in these articles and blog entries has been written without AI/GenAI, except I sometimes use a spellchecker to fix errors. Think Word's spellchecker, not ChatGPT.

Notes, as of today (2026-05-06):

  • No code snippet has been automatically generated, nor vibe-coded, nor generated and reviewed.
  • I don’t have any article with AI contribution.

For future entries:

  • I may have used GenAI for the code in the repo. The code I exemplify/copy in the article will always be reviewed and tested, not vibe-coded. I will specify it in each snippet or at the top/bottom of the article.
  • I normally don't use it for the text contents, although if I have used it for the article text, it would be indicated as such.

Any entry before 2026-05-06 does not contain any AI/GenAI.

For more information, read the AI/GenAI Policy

The value of worthless projects Building private tools in the open