<commit_before># FRP tools

Observer and computed value stores designed to work together for storing real state and derived state.

# [observable](./src/observable.js)

`observable` is a simple value store that can report when its value changes. It is good for wrapping external props passed into a component so compute types can dependent on them.

## Usage

### Creation

Creates and sets initial value to `true`

```js
const inViewport = observable(true);
```

### Read

Call it to receive the stored value.

```js
if (inViewport()) { /* inViewport is truthy */ }
```

### Change

Call it passing the new value. If any computed stores depend on this value they will be marked dirty and re-evaluated the next time they are read from.

```js
inViewport(false);
```

### Subscribe to changes

Call the `subscribe` method with a callback that will be called when the observable is changed to a different value.  The returned function can be called to unsubscribe from the observable.

```js
const unsubscribe = inViewport.subscribe(console.log.bind(console))
```


# [computed](./src/computed.js)

`computed` is a functional store that depends on the values of observables or other computeds. They derive value from observables rather than store value and hence cannot be set directly.

## Behavior
A `computed` will subscribe to its dependencies in such a way that it will be marked as *dirty* when any dependency changes. Whenever it is read from, if will recompute its result if the *dirty* flag is set, otherwise it just return the stored result from the last time it computed.

## Usage

### Creation

```js
const showDialog = computed(
    (inVP, shouldShow) => (inVP && shouldShow),  // computation function
    [inViewport, shouldShow]  // array of dependencies, can be either observable or computed
);
```

### Read
```js
if (showDialog()) { /* showDialog() is truthy */ }
```

Call it to receive the stored value, recomputing if necessary.


### Subscribe to changes

Call the subscribe method with a callback that will be called when the computed result changes to a different value.  The returned function can be called to unsubscribe from the observable.

```js
const unsubscribe = inViewport.subscribe(console.log.bind(console))
```

**NOTE**: Subscribing to a computed forces it to recompute every time an upstream dependency changes.  This could negatively performance if it depends on multiple values that change sequentially and the computation function is non-trivial.  For example:

```js
const inViewport = observable(false);
const shouldShow = observable(false);

const showDialog = computed(
    (inVP, shouldShow) => (inVP && shouldShow),
    [inViewport, shouldShow]
);

inViewport(true);  // showDialog marked as dirty but does not recompute its stored result.
shouldShow(true);  // showDialog is already marked as dirty. Nothing else happens.
showDialog();  // showDialog recomputes its stored result and unsets the dirty flag.

showDialog.subscribe(console.log.bind(console));

inViewport(false);  // showDialog result recomputed and `false` is written to the console.
shouldShow(false);  // showDialog result recomputed, console.log is not called.
showDialog();  // showDialog does not recompute, console.log is not called. `false` is returned.
```<commit_msg>A note for added clarity<commit_after># FRP tools

Observer and computed value stores designed to work together for storing real state and derived state.

# [observable](./src/observable.js)

`observable` is a simple value store that can report when its value changes. It is good for wrapping external props passed into a component so compute types can dependent on them.

## Usage

### Creation

Creates and sets initial value to `true`

```js
const inViewport = observable(true);
```

### Read

Call it to receive the stored value.

```js
if (inViewport()) { /* inViewport is truthy */ }
```

### Change

Call it passing the new value. If any computed stores depend on this value they will be marked dirty and re-evaluated the next time they are read from.

```js
inViewport(false);
```

### Subscribe to changes

Call the `subscribe` method with a callback that will be called when the observable is changed to a different value.  The returned function can be called to unsubscribe from the observable.

```js
const unsubscribe = inViewport.subscribe(console.log.bind(console))
```


# [computed](./src/computed.js)

`computed` is a functional store that depends on the values of observables or other computeds. They derive value from observables rather than store value and hence cannot be set directly.

## Behavior
A `computed` will subscribe to its dependencies in such a way that it will be marked as *dirty* when any dependency changes. Whenever it is read from, if will recompute its result if the *dirty* flag is set, otherwise it just return the stored result from the last time it computed.

## Usage

### Creation

```js
const showDialog = computed(
    (inVP, shouldShow) => (inVP && shouldShow),  // computation function
    [inViewport, shouldShow]  // array of dependencies, can be either observable or computed
);
```

### Read
```js
if (showDialog()) { /* showDialog() is truthy */ }
```

Call it to receive the stored value, recomputing if necessary.


### Subscribe to changes

Call the subscribe method with a callback that will be called when the computed result changes to a different value.  The returned function can be called to unsubscribe from the observable.

```js
const unsubscribe = inViewport.subscribe(console.log.bind(console))
```

**NOTE**: Subscribing to a computed forces it to recompute every time an upstream dependency changes.  This could negatively performance if it depends on multiple values that change sequentially and the computation function is non-trivial.  For example:

```js
const inViewport = observable(false);
const shouldShow = observable(false);

const showDialog = computed(
    (inVP, shouldShow) => (inVP && shouldShow),
    [inViewport, shouldShow]
);

inViewport(true);  // showDialog marked as dirty but does not recompute its stored result.
shouldShow(true);  // showDialog is already marked as dirty. Nothing else happens.
showDialog();  // showDialog recomputes its stored result and unsets the dirty flag.

// adding a subscription will change showDialog's internal behavior
showDialog.subscribe(console.log.bind(console));

inViewport(false);  // showDialog result recomputed and `false` is written to the console.
shouldShow(false);  // showDialog result recomputed, console.log is not called.
showDialog();  // showDialog does not recompute, console.log is not called. `false` is returned.
```
{'fraction_non_alphanumeric': 0.08610067618332082, 'fraction_numerical': 0.0, 'mean_word_length': 4.4557377049180324, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5689378', 'n_tokens_mistral': 1786, 'n_tokens_neox': 1702, 'n_words': 864}