aboutsummaryrefslogtreecommitdiff
path: root/README.rst
diff options
context:
space:
mode:
Diffstat (limited to 'README.rst')
-rw-r--r--README.rst123
1 files changed, 123 insertions, 0 deletions
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..e14d321
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,123 @@
+immutables
+==========
+
+.. image:: https://github.com/MagicStack/immutables/workflows/Tests/badge.svg?branch=master
+ :target: https://github.com/MagicStack/immutables/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush
+
+.. image:: https://img.shields.io/pypi/v/immutables.svg
+ :target: https://pypi.python.org/pypi/immutables
+
+An immutable mapping type for Python.
+
+The underlying datastructure is a Hash Array Mapped Trie (HAMT)
+used in Clojure, Scala, Haskell, and other functional languages.
+This implementation is used in CPython 3.7 in the ``contextvars``
+module (see `PEP 550 <https://www.python.org/dev/peps/pep-0550/>`_ and
+`PEP 567 <https://www.python.org/dev/peps/pep-0567/>`_ for more details).
+
+Immutable mappings based on HAMT have O(log N) performance for both
+``set()`` and ``get()`` operations, which is essentially O(1) for
+relatively small mappings.
+
+Below is a visualization of a simple get/set benchmark comparing
+HAMT to an immutable mapping implemented with a Python dict
+copy-on-write approach (the benchmark code is available
+`here <https://gist.github.com/1st1/292e3f0bbe43bd65ff3256f80aa2637d>`_):
+
+.. image:: bench.png
+
+
+Installation
+------------
+
+``immutables`` requires Python 3.6+ and is available on PyPI::
+
+ $ pip install immutables
+
+
+API
+---
+
+``immutables.Map`` is an unordered immutable mapping. ``Map`` objects
+are hashable, comparable, and pickleable.
+
+The ``Map`` object implements the ``collections.abc.Mapping`` ABC
+so working with it is very similar to working with Python dicts:
+
+.. code-block:: python
+
+ import immutables
+
+ map = immutables.Map(a=1, b=2)
+
+ print(map['a'])
+ # will print '1'
+
+ print(map.get('z', 100))
+ # will print '100'
+
+ print('z' in map)
+ # will print 'False'
+
+Since Maps are immutable, there is a special API for mutations that
+allow apply changes to the Map object and create new (derived) Maps:
+
+.. code-block:: python
+
+ map2 = map.set('a', 10)
+ print(map, map2)
+ # will print:
+ # <immutables.Map({'a': 1, 'b': 2})>
+ # <immutables.Map({'a': 10, 'b': 2})>
+
+ map3 = map2.delete('b')
+ print(map, map2, map3)
+ # will print:
+ # <immutables.Map({'a': 1, 'b': 2})>
+ # <immutables.Map({'a': 10, 'b': 2})>
+ # <immutables.Map({'a': 10})>
+
+Maps also implement APIs for bulk updates: ``MapMutation`` objects:
+
+.. code-block:: python
+
+ map_mutation = map.mutate()
+ map_mutation['a'] = 100
+ del map_mutation['b']
+ map_mutation.set('y', 'y')
+
+ map2 = map_mutation.finish()
+
+ print(map, map2)
+ # will print:
+ # <immutables.Map({'a': 1, 'b': 2})>
+ # <immutables.Map({'a': 100, 'y': 'y'})>
+
+``MapMutation`` objects are context managers. Here's the above example
+rewritten in a more idiomatic way:
+
+.. code-block:: python
+
+ with map.mutate() as mm:
+ mm['a'] = 100
+ del mm['b']
+ mm.set('y', 'y')
+ map2 = mm.finish()
+
+ print(map, map2)
+ # will print:
+ # <immutables.Map({'a': 1, 'b': 2})>
+ # <immutables.Map({'a': 100, 'y': 'y'})>
+
+
+Further development
+-------------------
+
+* An immutable version of Python ``set`` type with efficient
+ ``add()`` and ``discard()`` operations.
+
+
+License
+-------
+
+Apache 2.0