MergedObservable¶
Observables that combine multiple values using the merge operator (+
).
FynX MergedObservable - Combined Reactive Values¶
This module provides the MergedObservable class, which combines multiple individual observables into a single reactive computed observable. This enables treating related observables as a cohesive group that updates atomically when any component changes.
Merged observables are read-only computed observables that derive their value from their source observables. They are useful for:
- Coordinated Updates: When multiple values need to change together
- Computed Relationships: When derived values depend on multiple inputs
- Tuple Operations: When you need to pass multiple reactive values as a unit
- State Composition: Building complex state from simpler reactive components
The merge operation is created using the +
operator between observables:
from fynx import observable
width = observable(10)
height = observable(20)
dimensions = width + height # Creates MergedObservable
print(dimensions.value) # (10, 20)
width.set(15)
print(dimensions.value) # (15, 20)
# Merged observables are read-only
dimensions.set((5, 5)) # Raises ValueError: Computed observables are read-only
MergedObservable ¶
A computed observable that combines multiple observables into a single reactive tuple.
MergedObservable creates a read-only computed observable whose value is a tuple containing the current values of all source observables. When any source observable changes, the merged observable automatically recalculates its tuple value and notifies all subscribers.
As a computed observable, MergedObservable is read-only and cannot be set directly. Its value is always derived from its source observables, ensuring consistency.
This enables treating multiple related reactive values as a single atomic unit, which is particularly useful for:
- Functions that need multiple related parameters
- Computed values that depend on several inputs
- Coordinated state updates across multiple variables
- Maintaining referential consistency between related values
Example
from fynx import observable
# Individual observables
x = observable(10)
y = observable(20)
# Merge them into a single reactive unit
point = x + y
print(point.value) # (10, 20)
# Computed values can work with the tuple
distance_from_origin = point.then(
lambda px, py: (px**2 + py**2)**0.5
)
print(distance_from_origin.value) # 22.360679774997898
# Changes to either coordinate update everything
x.set(15)
print(point.value) # (15, 20)
print(distance_from_origin.value) # 25.0
Note
The merged observable's value is always a tuple, even when merging just two observables. This provides a consistent interface for computed functions.
See Also
ComputedObservable: Base computed observable class
operator: For creating derived values from merged observables
Create a merged observable from multiple source observables.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*observables
|
Observable
|
Variable number of Observable instances to combine. At least one observable must be provided. |
()
|
Raises:
Type | Description |
---|---|
ValueError
|
If no observables are provided |
value ¶
Get the current tuple value, using cache when possible.
Returns the current values of all source observables as a tuple. Uses caching to avoid recomputing the tuple on every access.
Returns:
Type | Description |
---|---|
A tuple containing the current values of all source observables, |
|
in the order they were provided to the constructor. |
__add__ ¶
Chain merging with another observable using the + operator.
Enables fluent syntax for building up merged observables incrementally. Each + operation creates a new MergedObservable containing all previous observables plus the new one.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
Observable
|
Another Observable to merge with this merged observable |
required |
Returns:
Type | Description |
---|---|
MergedObservable
|
A new MergedObservable containing all source observables from this |
MergedObservable
|
merged observable plus the additional observable. |
__enter__ ¶
Context manager entry for reactive blocks.
Enables experimental syntax for defining reactive blocks that execute whenever any of the merged observables change.
Returns:
Type | Description |
---|---|
A context object that can be called with a function to create reactive behavior. |
Example
Note
This is an experimental feature. The more common approach is to use subscribe() or the @reactive decorator.
__exit__ ¶
Context manager exit.
Currently does nothing, but allows the context manager to work properly.
subscribe ¶
Subscribe a function to react to changes in any of the merged observables.
The subscribed function will be called whenever any source observable changes. This provides a way to react to coordinated changes across multiple observables.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func
|
Callable
|
A callable that will receive the current values of all merged observables as separate arguments, in the order they were merged. The function signature should match the number of merged observables. |
required |
Returns:
Type | Description |
---|---|
MergedObservable[T]
|
This merged observable instance for method chaining. |
Examples:
x = Observable("x", 1)
y = Observable("y", 2)
coords = x + y
def on_coords_change(x_val, y_val):
print(f"Coordinates: ({x_val}, {y_val})")
coords.subscribe(on_coords_change)
x.set(10) # Prints: "Coordinates: (10, 2)"
y.set(20) # Prints: "Coordinates: (10, 20)"
Note
The function is called only when observables change. It is not called immediately upon subscription.
See Also
unsubscribe: Remove a subscription reactive: Decorator-based reactive functions
unsubscribe ¶
Unsubscribe a function from this merged observable.
Removes the subscription for the specified function, preventing it from being called when the merged observable changes. This properly cleans up the reactive context and removes all observers.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func
|
Callable
|
The function that was previously subscribed to this merged observable. Must be the same function object that was passed to subscribe(). |
required |
Examples:
def handler(x, y):
print(f"Changed: {x}, {y}")
coords = x + y
coords.subscribe(handler)
# Later, unsubscribe
coords.unsubscribe(handler) # No longer called when coords change
Note
This only removes subscriptions to this specific merged observable. If the same function is subscribed to other observables, those subscriptions remain active.
See Also
subscribe: Add a subscription