Core Concepts
Latent Objects
A Latent object is the fundamental building block in LatenPy. It represents a computation that:
Is defined but not immediately executed
Tracks its dependencies automatically
Caches its results
Only computes when explicitly requested
Creating Latent Objects
Use the @latent decorator to create functions that return Latent objects:
from latenpy import latent
@latent
def my_function(x):
return x * 2
# Creates a Latent object
result = my_function(5)
# Computation happens here
value = result.compute()
Dependency Tracking
LatenPy automatically builds a directed acyclic graph (DAG) of computations:
Nodes represent individual computations
Edges represent dependencies between computations
- The graph is used to determine:
What needs to be recomputed
What can be reused from cache
The order of computations
Example:
@latent
def add(a, b):
return a + b
@latent
def multiply(a, b):
return a * b
# Creates a dependency chain
x = multiply(2, 3)
y = add(x, 4)
# You can visualize the dependency graph
y.visualize()
When the parameters of a latent object are changed, the dependency graph is updated
automatically. You can update the parameters of a latent object by using the update
methods.
@latent
def add(a, b, offset=0):
return a + b + offset
@latent
def multiply(a, b):
return a * b
# Creates a dependency chain
x = multiply(2, 3)
y = add(x, 4, offset=0)
result = y.compute()
print(result)
# Update the parameters of the latent object
x.update_args(4, 5)
result = y.compute()
print(result)
# You can also update the keyword arguments of a latent object
x.update_kwargs(offset=1)
result = y.compute()
print(result)
# You can even update the function itself
x.update_func(lambda a, b: a ** b)
result = y.compute()
print(result)
Caching System
Smart Caching
Results are automatically cached when computed:
Cached results are reused when possible
Cache is invalidated when dependencies change
Cache Control
You can control caching behavior:
# Clear cache for a specific computation
result.clear_cache()
# Check if result is cached
is_cached = bool(result.latent_data)
Best Practices
- Use latent objects for:
Expensive calculations
Results you might need multiple times
Complex dependency chains
- Clear caches when:
Memory usage is high
Results are no longer needed
You want to force recomputation
- Visualize dependency graphs to:
Understand computation flow
Debug complex pipelines
Optimize computation chains