Skip to content

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

MergedObservable(*observables)

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

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.

Example
from fynx import observable

x = observable(10)
y = observable(20)
merged = x + y

print(merged.value)  # (10, 20)
x.set(15)
print(merged.value)  # (15, 20) - cache invalidated and recomputed

__add__

__add__(other: ObservableOperand[U]) -> 'MergedObservable[Unpack[Ts], U]'
__add__(other: Any) -> Any
__add__(other)

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__

__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
# Experimental context manager syntax
with merged_obs as ctx:
    ctx(lambda x, y: print(f"Values changed: {x}, {y}"))
Note

This is an experimental feature. The more common approach is to use subscribe() or the @reactive decorator.

__exit__

__exit__(exc_type, exc_val, exc_tb)

Context manager exit.

Currently does nothing, but allows the context manager to work properly.

__rshift__

__rshift__(func)

Transform a merged observable with an unpacked product callback.

subscribe

subscribe(func)

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

then

then(func)

Transform a merged observable by unpacking its tuple value.

unsubscribe

unsubscribe(func)

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