MergedObservable¶
Observables that combine multiple values using the merge operator (+).
FynX MergedObservable - combined reactive values¶
MergedObservable combines multiple observables into a single reactive tuple - like a coordinate pair where x and y need to be read together.
It's a read-only computed observable whose value is a tuple of the current values of all its sources. Reading it is lazy and version-validated: the tuple only refreshes if a source's version changed since the last read. Subscribing creates the eager boundary needed to deliver notifications when any source changes.
The merge operation uses the + operator between observables, producing a
new MergedObservable containing both values as a tuple:
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 and cannot be set directly
That gives you multiple reactive values that behave as a single atomic unit - useful for functions that need several related parameters, computed values that depend on more than one input, or state updates coordinated across several variables.
MergedObservable ¶
A computed observable that combines multiple observables into a single reactive tuple.
Change any source value and the next read sees a fresh tuple; if the
product is observed, source changes also notify subscribers directly with
the updated tuple. Products are canonical for a given ordered source
list while live, so repeated a + b expressions reuse the same product
node rather than creating a new one each time.
Like any computed observable, a MergedObservable is read-only - its value always derives from its sources, so setting it directly would let it diverge from them.
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
The value is always a tuple, even when merging just two observables, so computed functions get a uniform interface regardless of how many observables went in.
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[Any]'
|
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 |
|---|---|
tuple[Unpack[Ts]]
|
A tuple containing the current values of all source observables, |
tuple[Unpack[Ts]]
|
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. The result is the canonical ordered product containing all previous observables plus the new one while that product is live.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Any
|
Another Observable to merge with this merged observable |
required |
Returns:
| Type | Description |
|---|---|
Any
|
A MergedObservable containing all source observables from this |
Any
|
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 |
|---|---|
Any
|
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[[Unpack[Ts]], object]
|
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[Unpack[Ts]]'
|
This merged observable instance for method chaining. |
Examples:
from fynx import observable
x = observable(1)
y = observable(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)"
The function is called only when a source changes - not immediately on subscription, so subscribing doesn't trigger an unnecessary initial call.
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[[Unpack[Ts]], object]
|
The function that was previously subscribed to this merged observable. Must be the same function object that was passed to subscribe(). |
required |
Examples:
from fynx import observable
x = observable(1)
y = observable(2)
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
This only removes the subscription on this merged observable - if the same function is also subscribed elsewhere, those subscriptions stay active.
See Also
subscribe: Add a subscription