CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-lenses

A lens library for python that enables immutable manipulation of deeply nested data structures

Pending
Overview
Eval results
Files

core-lenses.mddocs/

Core Lens Operations

The fundamental lens interface providing get, set, modify operations and lens composition. These core operations form the foundation of all lens-based data manipulation in the library.

Capabilities

UnboundLens

The main lens class that provides composable data access patterns without being bound to specific state. All lens constructors return UnboundLens instances.

class UnboundLens:
    def __init__(self, optic): ...
    
    def get(self) -> StateFunction[S, B]:
        """Get the first value focused by the lens."""
    
    def collect(self) -> StateFunction[S, List[B]]:
        """Get multiple values focused by the lens as a list."""
    
    def get_monoid(self) -> StateFunction[S, B]:
        """Get values focused by the lens, merging them as a monoid."""
    
    def set(self, newvalue: B) -> StateFunction[S, T]:
        """Set the focus to newvalue."""
    
    def set_many(self, new_values: Iterable[B]) -> StateFunction[S, T]:
        """Set many foci to values from new_values iterable."""
    
    def modify(self, func: Callable[[A], B]) -> StateFunction[S, T]:
        """Apply a function to the focus."""
    
    def construct(self, focus: A) -> S:
        """Construct a state given a focus."""
    
    def flip(self) -> UnboundLens[A, B, S, T]:
        """Flips the direction of the lens (requires isomorphisms)."""
    
    def kind(self) -> str:
        """Returns the 'kind' of the lens."""
    
    def __and__(self, other) -> UnboundLens:
        """Compose this lens with another lens or apply function to focus."""
    
    def add_lens(self, other) -> UnboundLens:
        """Alias for __and__."""

Usage Examples

from lenses import lens

# Basic getting
data = [1, 2, 3]
first = lens[0].get()(data)  # 1

# Setting creates new data structures
new_data = lens[1].set(99)(data)  # [1, 99, 3]

# Modifying with functions
doubled = lens.Each().modify(lambda x: x * 2)(data)  # [2, 4, 6]

# Lens composition with &
nested = [[1, 2], [3, 4], [5, 6]]
first_of_each = lens.Each()[0].collect()(nested)  # [1, 3, 5]

# Function application with &  
add_ten = lens[0] & (lambda x: x + 10)
result = add_ten(data)  # [11, 2, 3]

BoundLens

A lens that has been bound to specific state, providing direct access without needing to pass state as a parameter.

class BoundLens:
    def __init__(self, state: S, optic) -> None: ...
    
    def get(self) -> B:
        """Get the first value focused by the lens."""
    
    def collect(self) -> List[B]:
        """Get multiple values focused by the lens as a list."""
    
    def get_monoid(self) -> B:
        """Get values focused by the lens, merging them as a monoid."""
    
    def set(self, newvalue: B) -> T:
        """Set the focus to newvalue."""
    
    def set_many(self, new_values: Iterable[B]) -> T:
        """Set many foci to values from new_values iterable."""
    
    def modify(self, func: Callable[[A], B]) -> T:
        """Apply a function to the focus."""
    
    def kind(self) -> str:
        """Returns the 'kind' of the lens."""
    
    def __and__(self, other) -> BoundLens:
        """Compose this lens with another lens or apply function to focus."""
    
    def add_lens(self, other) -> BoundLens:
        """Alias for __and__."""

Usage Examples

from lenses import bind

# Create bound lens
data = {"users": [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]}
bound = bind(data)

# Direct operations without passing state
first_user_name = bound["users"][0]["name"].get()  # "Alice"
updated_data = bound["users"][0]["age"].set(26)

# Composition works the same
all_ages = bound["users"].Each()["age"].collect()  # [25, 30]

StateFunction

A wrapper for functions that operate on state, returned by UnboundLens operations.

class StateFunction:
    def __init__(self, func: Callable[[S], T]): ...
    def __call__(self, state: S) -> T: ...

Usage Examples

from lenses import lens

# Get operations return StateFunctions
getter = lens[0].get()  # StateFunction
value = getter([1, 2, 3])  # 1

# Set operations return StateFunctions  
setter = lens[1].set(99)  # StateFunction
new_list = setter([1, 2, 3])  # [1, 99, 3]

Bind Function

Creates a BoundLens from state, providing an alternative entry point to the lens system.

def bind(state: S) -> BoundLens[S, S, S, S]:
    """Returns a simple BoundLens object bound to state."""

Usage Examples

from lenses import bind

# Create bound lens for immediate operations
data = [1, 2, 3, 4, 5]  
bound_data = bind(data)

# Perform operations directly
first = bound_data[0].get()  # 1
modified = bound_data.Each().modify(lambda x: x + 1)  # [2, 3, 4, 5, 6]

# Useful for method chaining
result = (bind({"a": [1, 2, 3]})
          ["a"]
          .Each()
          .modify(lambda x: x * 2)
          .collect())  # [2, 4, 6] from modified state

Lens Composition

Lenses can be composed using the & operator to create complex data access patterns.

# Composition operator
lens_a & lens_b  # Compose two lenses
lens_a & function  # Apply function to lens focus

Composition Examples

from lenses import lens

# Nested data access
data = [{"values": [1, 2, 3]}, {"values": [4, 5, 6]}]

# Compose lenses to access nested values
each_first_value = lens.Each()["values"][0]
first_values = each_first_value.collect()(data)  # [1, 4]

# Function composition
multiply_by_ten = lens.Each() & (lambda x: x * 10)
result = multiply_by_ten([1, 2, 3])  # [10, 20, 30]

# Complex composition chains
complex_lens = (lens["data"]
                .Each()
                .Filter(lambda x: x > 0)
                ["value"]
                .modify(lambda x: x * 2))

Install with Tessl CLI

npx tessl i tessl/pypi-lenses

docs

core-lenses.md

index.md

lens-constructors.md

optics.md

utility-types.md

tile.json