SkillAgentSearch skills...

Clj

:koala: (Clojure-like) Lazy iterators in Python

Install / Use

/learn @bfontaine/Clj
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

clj

clj is a collection of functions to work with lazy iterators in Python.

It’s a module for those times when you did too much Clojure and came back to Python wondering where are all these distinct, drop-while, cycle, first, etc.

The library is oriented toward laziness and performance. Functions are implemented with as little overhead as possible.

Install

pip install clj

Python requirement:

  • 0.4.x: Python 3.9+
  • 0.3.x: Python 3.7+
  • 0.2.x: Python 3.7+
  • 0.1.x: Python 2.7, 3.3+

Usage

The library is considered stable and is used in production.

Example

;; Clojure
(->> coll (map inc) (filter even?) distinct count println)
; which expands to:
(println (count (distinct (filter even? (map inc coll)))))
# Python
from clj import count, distinct, inc, is_even

print(count(distinct(filter(is_even, map(inc, coll)))))

Note that count() works on both sequences in generators; in the latter case it doesn’t load everything in memory like e.g. len(list(g)) would do.

Core Ideas

  • Lazy by default. All functions should work on arbitrary iterators and return generators.
  • This is Python. We keep Python’s semantics instead of trying to reproduce Clojure in Python (e.g. 0 and [] are logically true in Clojure but false in Python; None is not equivalent to an empty collection).
  • Don’t Reinvent the Wheel. We don’t reimplement built-in functions unless they miss something, like range that can’t be called without argument to yield an infinite sequence.

Support

The general naming scheme is: use underscores instead of hyphens; start the function with is_ if its Clojure counterparts ends with a ?.

Sequences

We aim to implement all Clojure functions that operate on sequences (see the list here). They all work on iterables and return generators by default (Python’s closest equivalent of lazy seqs). We don’t support transducers.

| Clojure | clj | Comment | |-------------------|:----------------|---------------------------------------------------------------------------------------------------------------------| | distinct | distinct | | | filter | filter | Alias to Python’s built-in filter. | | remove | remove | | | keep | keep | | | keep-indexed | keep_indexed | | | cons | cons | | | concat | concat | Equivalent to itertools.chain. | | lazy-cat | - | Use Python’s itertools.chain. | | mapcat | mapcat | | | cycle | cycle | | | interleave | interleave | | | interpose | interpose | | | rest | rest | | | next | - | Use rest. | | fnext | - | Use second. | | nnext | - | Use rest(rest(…)) | | drop | drop | | | drop-while | drop_while | Equivalent to itertools.dropwhile. | | nthnext | - | Use drop. | | take | take | | | take-nth | take_nth | | | take-while | take_while | Equivalent to itertools.takewhile. | | butlast | butlast | | | drop-last | drop_last | | | flatten | flatten | | | reverse | reverse | | | sort | - | Use Python’s built-in sort. | | sort-by | - | Use sort(…, key=your_function). | | shuffle | shuffle | | | split-at | split_at | | | split-with | split_with | | | partition | partition | (partition n step pad coll) becomes partition(coll, n, step, pad). Only the case step=n is supported for now. | | partition-all | | | | partition-by | partition_by | | | map | map | Alias to Python’s built-in map. | | pmap | - | | | replace | replace | | | reductions | reductions | (reductions f i c) becomes reductions(f, c, i). | | map-indexed | map_indexed | | | seque | - | | | first | first | None is not a valid parameter. | | ffirst | ffirst | None is not a valid parameter. | | nfirst | nfirst | | | second | second | | | nth | nth | | | last | last | | | rand-nth | - | Use Python’s random.choice. | | zipmap | zipmap | | | into | - |

View on GitHub
GitHub Stars24
CategoryDevelopment
Updated3mo ago
Forks4

Languages

Python

Security Score

92/100

Audited on Dec 28, 2025

No findings