# Pyrsistent

A comprehensive Python library providing persistent/immutable data structures. Pyrsistent enables functional programming patterns by offering immutable alternatives to Python's built-in collections (dict, list, set) that never modify in-place but return new instances with requested changes, enabling safer concurrent programming and easier reasoning about program state.

## Package Information

- **Package Name**: pyrsistent
- **Language**: Python
- **Installation**: `pip install pyrsistent`

## Core Imports

```python
import pyrsistent
```

Common imports for working with specific data structures:

```python
from pyrsistent import pmap, pvector, pset, freeze, thaw
```

For type checking and records:

```python
from pyrsistent import PRecord, PClass, field
```

For type annotations:

```python
from typing import Union, Mapping, Iterable, Tuple, TypeVar, Any
KT = TypeVar('KT')  # Key type
VT = TypeVar('VT')  # Value type  
T = TypeVar('T')    # Element type
```

## Basic Usage

```python
from pyrsistent import pmap, pvector, pset, freeze, thaw

# Create persistent collections
pm = pmap({'name': 'John', 'age': 30})
pv = pvector([1, 2, 3, 4, 5])
ps = pset([1, 2, 3, 3, 4])  # Duplicate 3 is automatically removed

# All operations return new instances
pm2 = pm.set('age', 31)  # pm is unchanged
pv2 = pv.append(6)       # pv is unchanged
ps2 = ps.add(5)          # ps is unchanged

print(pm2)  # pmap({'name': 'John', 'age': 31})
print(pv2)  # pvector([1, 2, 3, 4, 5, 6])
print(ps2)  # pset([1, 2, 3, 4, 5])

# Convert between mutable and immutable
regular_dict = {'a': 1, 'b': [2, 3], 'c': {4, 5}}
persistent = freeze(regular_dict)  # Recursively converts to persistent
mutable = thaw(persistent)         # Recursively converts back to mutable
```

## Architecture

Pyrsistent provides two main categories of persistent data structures:

- **Core Collections**: Immutable versions of Python's built-in collections with structural sharing for memory efficiency
- **Type-Checked Collections**: Enhanced versions with runtime type validation and invariant checking
- **Record Types**: Fixed-schema data structures for structured data modeling

All collections use structural sharing through Hash Array Mapped Tries (HAMT) and similar data structures, enabling O(log32 n) performance for most operations while minimizing memory usage.

## Capabilities

### Core Persistent Collections

Immutable alternatives to Python's built-in collections including persistent map (dict), vector (list), set, bag (multiset), list (linked), and deque (double-ended queue). All operations return new instances with structural sharing for efficiency.

```python { .api }
def pmap(initial: Union[Mapping[KT, VT], Iterable[Tuple[KT, VT]]] = {}, pre_size: int = 0) -> PMap[KT, VT]: ...
def pvector(iterable: Iterable[T] = ()) -> PVector[T]: ...
def pset(iterable: Iterable[T] = (), pre_size: int = 8) -> PSet[T]: ...
def pbag(elements: Iterable[T]) -> PBag[T]: ...
def plist(iterable: Iterable[T] = (), reverse: bool = False) -> PList[T]: ...
def pdeque(iterable: Iterable[T] = None, maxlen: int = None) -> PDeque[T]: ...
```

[Core Collections](./core-collections.md)

### Type-Checked Collections

Runtime type validation for persistent collections with optional invariant checking. Provides CheckedPMap, CheckedPVector, and CheckedPSet with customizable type constraints and validation rules.

```python { .api }
class CheckedPMap(PMap):
    __key_type__: type
    __value_type__: type

class CheckedPVector(PVector):
    __type__: type

class CheckedPSet(PSet):
    __type__: type

def optional(*types) -> tuple: ...
```

[Type-Checked Collections](./type-checked-collections.md)

### Records and Classes

Structured data types with fixed schemas, type checking, and serialization support. PRecord provides a dict-like interface while PClass provides an object-like interface, both with field specifications and validation.

```python { .api }
class PRecord(PMap):
    def set(self, *args, **kwargs) -> 'PRecord': ...
    @classmethod
    def create(cls, kwargs: dict, ignore_extra: bool = False) -> 'PRecord': ...
    def serialize(self, format=None) -> dict: ...

class PClass:
    def set(self, *args, **kwargs) -> 'PClass': ...
    @classmethod
    def create(cls, kwargs: dict, ignore_extra: bool = False) -> 'PClass': ...
    def serialize(self, format=None) -> dict: ...

def field(type=(), invariant=..., initial=..., mandatory: bool = False, factory=..., serializer=...) -> 'PField': ...
```

[Records and Classes](./records-and-classes.md)

### Utilities and Transformations

Helper functions for converting between mutable and immutable structures, applying transformations, and accessing nested data. Includes freeze/thaw conversion, transformation functions, and nested access utilities.

```python { .api }
def freeze(obj, strict: bool = True): ...
def thaw(obj, strict: bool = True): ...
def mutant(fn) -> callable: ...
def get_in(keys: Iterable, coll: Mapping, default=None, no_default: bool = False): ...
def inc(x: int) -> int: ...
def discard(evolver, key) -> None: ...
```

[Utilities and Transformations](./utilities.md)