Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d33bc9e1 authored by Steve Elliott's avatar Steve Elliott
Browse files

[kairos] Rename kt-frp to Kairos

Flag: EXEMPT no code changed
Test: m kairos
Change-Id: I656f511ece24c5b03af340e156b98ed3d5213453
parent fc0806fb
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ package {
}

java_library {
    name: "kt-frp",
    name: "kairos",
    host_supported: true,
    kotlincflags: ["-opt-in=com.android.systemui.experimental.frp.ExperimentalFrpApi"],
    kotlincflags: ["-opt-in=com.android.systemui.kairos.ExperimentalFrpApi"],
    srcs: ["src/**/*.kt"],
    static_libs: [
        "kotlin-stdlib",
@@ -31,7 +31,7 @@ java_library {
}

java_test {
    name: "kt-frp-test",
    name: "kairos-test",
    optimize: {
        enabled: false,
    },
@@ -39,7 +39,7 @@ java_test {
        "test/**/*.kt",
    ],
    static_libs: [
        "kt-frp",
        "kairos",
        "junit",
        "kotlin-stdlib",
        "kotlin-test",
+4 −4
Original line number Diff line number Diff line
# kt-frp
# Kairos

A functional reactive programming (FRP) library for Kotlin.

@@ -13,12 +13,12 @@ FRP exposes an API that should be familiar to those versed in Kotlin `Flow`.

### Details for nerds

`kt-frp` implements an applicative / monadic flavor of FRP, using a push-pull
`Kairos` implements an applicative / monadic flavor of FRP, using a push-pull
methodology to allow for efficient updates.

"Real" functional reactive programming should be specified with denotational
semantics ([wikipedia](https://en.wikipedia.org/wiki/Denotational_semantics)):
you can view the semantics for `kt-frp` [here](docs/semantics.md).
you can view the semantics for `Kairos` [here](docs/semantics.md).

## Usage

@@ -61,4 +61,4 @@ will tear-down all effects and obervers running within the lambda.

## Resources

- [Cheatsheet for those coming from Kotlin Flow](docs/flow-to-frp-cheatsheet.md)
- [Cheatsheet for those coming from Kotlin Flow](docs/flow-to-kairos-cheatsheet.md)
+13 −13
Original line number Diff line number Diff line
# From Flows to FRP
# From Flows to Kairos

## Key differences

* FRP evaluates all events (`TFlow` emissions + observers) in a transaction.
* Kairos evaluates all events (`TFlow` emissions + observers) in a transaction.

* FRP splits `Flow` APIs into two distinct types: `TFlow` and `TState`
* Kairos splits `Flow` APIs into two distinct types: `TFlow` and `TState`

    * `TFlow` is roughly equivalent to `SharedFlow` w/ a replay cache that
      exists for the duration of the current FRP transaction and shared with
      exists for the duration of the current Kairos transaction and shared with
      `SharingStarted.WhileSubscribed()`

    * `TState` is roughly equivalent to `StateFlow` shared with
      `SharingStarted.Eagerly`, but the current value can only be queried within
      a FRP transaction, and the value is only updated at the end of the
      a Kairos transaction, and the value is only updated at the end of the
      transaction

* FRP further divides `Flow` APIs based on how they internally use state:
* Kairos further divides `Flow` APIs based on how they internally use state:

  * **FrpTransactionScope:** APIs that internally query some state need to be
    performed within an FRP transaction
    performed within an Kairos transaction

    * this scope is available from the other scopes, and from most lambdas
      passed to other FRP APIs
      passed to other Kairos APIs

  * **FrpStateScope:** APIs that internally accumulate state in reaction to
    events need to be performed within an FRP State scope (akin to a
@@ -126,8 +126,8 @@ has emitted at least once. This often bites developers. As a workaround,
developers generally append `.onStart { emit(initialValue) }` to the `Flows`
that don't immediately emit.

FRP avoids this gotcha by forcing usage of `TState` for `combine`, thus ensuring
that there is always a current value to be combined for each input.
Kairos avoids this gotcha by forcing usage of `TState` for `combine`, thus
ensuring that there is always a current value to be combined for each input.

## collect { … }

@@ -158,8 +158,8 @@ tFlow.map { tState.sample() }
#### Explanation

To keep all state-reads consistent, the current value of a TState can only be
queried within an FRP transaction, modeled with `FrpTransactionScope`. Note that
both `FrpStateScope` and `FrpBuildScope` extend `FrpTransactionScope`.
queried within a Kairos transaction, modeled with `FrpTransactionScope`. Note
that both `FrpStateScope` and `FrpBuildScope` extend `FrpTransactionScope`.

### I want to sample a TFlow

@@ -198,7 +198,7 @@ simultaneous emissions within the same transaction.

#### Explanation

Under FRP's rules, a `TFlow` may only emit up to once per transaction. This
Under Kairos's rules, a `TFlow` may only emit up to once per transaction. This
means that if we are merging two or more `TFlows` that are emitting at the same
time (within the same transaction), the resulting merged `TFlow` must emit a
single value. The lambda argument allows the developer to decide what to do in
+3 −3
Original line number Diff line number Diff line
# FRP Semantics

`kt-frp`'s pure API is based off of the following denotational semantics
`Kairos`'s pure API is based off of the following denotational semantics
([wikipedia](https://en.wikipedia.org/wiki/Denotational_semantics)).

The semantics model `kt-frp` types as time-varying values; by making `Time` a
The semantics model `Kairos` types as time-varying values; by making `Time` a
first-class value, we can define a referentially-transparent API that allows us
to reason about the behavior of the pure FRP combinators. This is
to reason about the behavior of the pure `Kairos` combinators. This is
implementation-agnostic; we can compare the behavior of any implementation with
expected behavior denoted by these semantics to identify bugs.

Loading