# Computables

Computables are streamable, composable values in Dart.

The current value of a computable is synchronously readable using `get()`.

``````final computable = Computable(2);
print(computable.get()) // 2
print(computable.get()) // 3
``````

## Streamable

The value of the computable can be reactively watched using `stream()`. The stream starts with the current value of the computable.

``````import 'package:computables/computables.dart';

final computable = Computable(2);

computable.stream().listen((value) {
print(value);
// 2
// 3
});

``````

## Composable

A computation is a type of computable that composes multiple input computables into a single output computable. The input to a computation can be any other computable value, including futures, streams and other computations.

``````final computation = Computation.compute2(
Computable.fromStream(Stream.value(1), initialValue: 0),
Computable.fromFuture(Future.value(2), initialValue: 0),
(input1, input2) => input1 + input2,
);

computable.stream().listen((value) {
print(value);
// 0
// 1
// 3
});
``````

Since a computation is just another type of computable, it can be immediately reused in other computations:

``````final computation = Computation.compute2(
Computable.fromStream(Stream.value(1), initialValue: 0),
Computable.fromFuture(Future.value(2), initialValue: 0),
(input1, input2) => input1 + input2,
);

Computation.compute2(
computation,
Computable(1),
(input1, input2) => input1 + input2,
).stream().listen((value) {
print(value);
// 1
// 2
// 4
});
``````

## Transformable

A computation maps multiple input values to a single output value.

A transformation maps multiple input values to a new computable that can emit one or more values.

``````final computable1 = Computable(1);
final computable2 = Computable(5);

Computation.transform2(
computable1,
computable2,
(input1, input2) {
return Computable.fromStream(
Stream.fromIterable(
List.generate(input2 - input1, (index) => index + 1),
),
initialValue: 0,
);
},
).stream.listen((value) {
print(value);
// 0
// 1
// 2
// 3
// 4
})
``````

The above transformation takes two computable values as inputs and returns a computable stream of values that begins with 0 and asynchronously emits the sequence 1, 2, 3, 4.

## Subscribers

A `ComputableSubscriber` allows a computable to subscribe to changes from other sources like futures, streams, and other computables.

``````final subscriber = Computable.subscriber(0);

subscriber.forward(Computable.fromStream(Stream.fromIterable([1, 2, 3])));
subscriber.forwardFuture(Future.delayed(Duration(seconds: 1), () => 4));

subscriber.stream().listen((value) {
print(value);
// 0
// 1
// 2
// 3
// 4
})
``````

## Extensions

There are some helpful utility extensions that make working with computables easier:

### Map

Map a source computable to a new computable:

``````final computable = Computable(2);
computable.map((value) => value + 1).stream().listen((value) {
print(value);
// 3
// 4
});

``````

### Transform

Transform a source computable to a new computable:

``````final computable = Computable(2);

computable.transform(
(value) => Computable.fromStream(
Stream.iterable([value + 1, value + 2, value + 3]),
initialValue: 0,
),
).stream().listen((value) {
print(value);
// 0
// 3
// 4
// 5
});
``````

## Contributing

Reach out if there's any functionality you'd like added and happy coding!

## Libraries

computables
widgets/computable_builder