Skip to main content

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 -
reduce - Use Python’s functools.reduce.
set - Use Python’s set.
vec - Use Python’s list.
into-array - Use Python’s list.
to-array-2d -
frequencies - Use Python’s collections.Counter.
group-by group_by
apply - Use the f(*args) construct.
not-empty -
some some
seq? is_seq
every? every
not-every? not_every
not-any? not_any
empty? -
empty empty
doseq - Use for … in.
dorun dorun
doall - Use Python’s list.
realized? -
seq - Use Python’s list.
vals - Use Python’s dict.values.
keys - Use Python’s dict.keys.
rseq -
subseq -
rsubseq -
repeatedly repeatedly
iterate iterate
repeat repeat (repeat n x) becomes repeat(x, n). Equivalent to itertools.repeat.
range range Prefer Python’s range for everything but infinite generators.
line-seq - Loop over an io.BufferedReader.
resultset-seq -
re-seq - Use Python’s re.finditer.
tree-seq tree_seq
file-seq - Use Python’s os.walk.
xml-seq -
iterator-seq -
enumeration-seq -
hash-map - Use Python’s dict.
array-map - Use Python’s dict.
sorted-map - Use collections.OrderedDict.
sorted-map-by -
hash-set - Use Python’s set.
set - Use Python’s set.
sorted-set -
sorted-set-by -
dedupe dedupe

We also implemented count, which uses Python’s len when possible and fallbacks on a for loop for other cases.

Functions

We also provide miscellaneous functions as well as functions that work on functions.

Clojure clj Comment
identity identity
partial - Use Python’s functools.partial
comp comp
complement complement
constantly constantly
juxt juxt
distinct? is_distinct
Clojure clj Comment
inc inc
dec dec

Metadata

Release files for clj 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for clj 0.5.0
File Size Uploaded Provenance Actions
clj-0.5.0.tar.gz 13.5 kB Without provenance Details for clj-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for clj 0.5.0
File Interpreter ABI Platform Actions
clj-0.5.0-py3-none-any.whl Python 3 none any Details for clj-0.5.0-py3-none-any.whl

Total release size: 25.9 kB

Release files / clj-0.5.0.tar.gz

Download URL clj-0.5.0.tar.gz
Size 13.5 kB
Tags Source
SHA-256 checksum
How to use checksums
fa33a63b71b42cf99a25dbe7663ad73c2f2a1dcdd5640e163dd97cc604e1882e
BLAKE2b-256 checksum
How to use checksums
0c4ab9c7560a79edaeb80d7c06c9dfdce56dc0e9a85fc7fbc05d1e132fdbde96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.9.21 Linux/6.11.0-1015-azure

Release files / clj-0.5.0-py3-none-any.whl

Download URL clj-0.5.0-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d8e7abd8d3ff4d5f82bd02c17f8741a34d63fe77d05772c760f2db4f0cf49b9
BLAKE2b-256 checksum
How to use checksums
181f3cba799b4a90bf5d8149066b8cc676c3a9d9712a1b1c0bda8c81ec0d02c0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.9.21 Linux/6.11.0-1015-azure

Security for clj 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page