diff --git a/.changeset/new-crabs-attack.md b/.changeset/new-crabs-attack.md new file mode 100644 index 0000000..e142e4e --- /dev/null +++ b/.changeset/new-crabs-attack.md @@ -0,0 +1,5 @@ +--- +"@effect-rx/rx": patch +--- + +fix \*Fn not running for constant return values diff --git a/docs/rx/Rx.ts.md b/docs/rx/Rx.ts.md index 2d4b3b5..ed5c5ba 100644 --- a/docs/rx/Rx.ts.md +++ b/docs/rx/Rx.ts.md @@ -25,6 +25,7 @@ Added in v1.0.0 - [effect](#effect) - [effectFn](#effectfn) - [family](#family) + - [fn](#fn) - [readable](#readable) - [runtime](#runtime) - [scoped](#scoped) @@ -212,6 +213,16 @@ export declare const family: >(f: (arg: Arg) => T) => (ar Added in v1.0.0 +## fn + +**Signature** + +```ts +export declare const fn: (f: Rx.ReadFn) => Writable, Arg> +``` + +Added in v1.0.0 + ## readable **Signature** diff --git a/packages/rx/src/Rx.ts b/packages/rx/src/Rx.ts index e7ecfb4..ea8f003 100644 --- a/packages/rx/src/Rx.ts +++ b/packages/rx/src/Rx.ts @@ -2,7 +2,7 @@ * @since 1.0.0 */ import * as internalRegistry from "@effect-rx/rx/internal/registry" -import { runCallbackSyncDefault } from "@effect-rx/rx/internal/runtime" +import { runCallbackSync, runCallbackSyncDefault } from "@effect-rx/rx/internal/runtime" import * as Result from "@effect-rx/rx/Result" import * as Chunk from "@effect/data/Chunk" import { dual, pipe } from "@effect/data/Function" @@ -14,7 +14,7 @@ import { NoSuchElementException } from "@effect/io/Cause" import * as Effect from "@effect/io/Effect" import * as Exit from "@effect/io/Exit" import * as Layer from "@effect/io/Layer" -import * as Runtime from "@effect/io/Runtime" +import type * as Runtime from "@effect/io/Runtime" import * as Scope from "@effect/io/Scope" import * as Stream from "@effect/stream/Stream" @@ -322,7 +322,7 @@ function makeEffectRuntime( return runtimeResult as any } - return makeEffect(ctx, create as any, Runtime.runCallback(runtimeResult.value)) + return makeEffect(ctx, create as any, runCallbackSync(runtimeResult.value)) } function makeScoped( @@ -344,6 +344,44 @@ function makeScoped( : makeEffect(ctx, createScoped as any) } +/** + * @since 1.0.0 + * @category constructors + */ +export const fn = (f: Rx.ReadFn): Writable, Arg> => { + const argRx = state<[number, Arg]>([0, undefined as any]) + return writable(function(get) { + const [counter, arg] = get(argRx) + if (counter === 0) { + return Option.none() + } + return Option.some(f(arg, get)) + }, function(ctx, arg) { + ctx.set(argRx, [ctx.get(argRx)[0] + 1, arg]) + }) +} + +function makeFn( + f: Rx.ReadFn, + transform: (get: Context, _: Option.Option>) => B +) { + const argRx = state<[number, Arg]>([0, undefined as any]) + return writable(function(get) { + const [counter, arg] = get(argRx) + if (counter === 0) { + return transform(get, Option.none()) + } + return transform( + get, + Option.some(function(ctx) { + return f(arg, ctx) + }) + ) + }, function(ctx, arg) { + ctx.set(argRx, [ctx.get(argRx)[0] + 1, arg]) + }) +} + /** * @since 1.0.0 * @category constructors @@ -401,27 +439,15 @@ export const effectFn: { } = ( f: Rx.ReadFn>, options?: { readonly runtime?: RxRuntime } -) => { - const argRx = state<[number, Arg]>([0, undefined as any]) - const effectRx = readable | undefined>(function(get) { - const [counter, arg] = get(argRx) - if (counter === 0) { - return undefined - } - return f(arg, get) - }) - return writable, Arg>(function(get) { - const effect = get(effectRx) - if (effect === undefined) { +) => + makeFn(f, function(get, create) { + if (create._tag === "None") { return Result.initial() } return options?.runtime - ? makeEffectRuntime(get, (_) => effect, options.runtime) - : makeEffect(get, (_) => effect as Effect.Effect) - }, function(ctx, arg) { - ctx.set(argRx, [ctx.get(argRx)[0] + 1, arg]) + ? makeEffectRuntime(get, create.value, options.runtime) + : makeEffect(get, create.value as any) }) -} /** * @since 1.0.0 @@ -436,25 +462,13 @@ export const scopedFn: { } = ( f: Rx.ReadFn>, options?: { readonly runtime?: RxRuntime } -) => { - const argRx = state<[number, Arg]>([0, undefined as any]) - const effectRx = readable | undefined>(function(get) { - const [counter, arg] = get(argRx) - if (counter === 0) { - return undefined - } - return f(arg, get) - }) - return writable, Arg>(function(get) { - const effect = get(effectRx) - if (effect === undefined) { +) => + makeFn(f, function(get, create) { + if (create._tag === "None") { return Result.initial() } - return makeScoped(get, (_) => effect, options) - }, function(ctx, arg) { - ctx.set(argRx, [ctx.get(argRx)[0] + 1, arg]) + return makeScoped(get, create.value, options) }) -} /** * @since 1.0.0 @@ -492,7 +506,7 @@ export const runtime: { function makeStream( ctx: Context, create: Rx.Read>, - runCallback = Effect.runCallback + runCallback = runCallbackSyncDefault ): Result.Result { const previous = ctx.self>() @@ -518,7 +532,9 @@ function makeStream( } } ) - ctx.addFinalizer(cancel) + if (cancel !== undefined) { + ctx.addFinalizer(cancel) + } if (previous._tag === "Some") { return Result.waitingFrom(previous) @@ -541,7 +557,7 @@ function makeStreamRuntime( return runtimeResult as any } - return makeStream(ctx, create as any, Runtime.runCallback(runtimeResult.value)) + return makeStream(ctx, create as any, runCallbackSync(runtimeResult.value)) } /** @@ -579,27 +595,16 @@ export const streamFn: { } = ( f: Rx.ReadFn>, options?: { readonly runtime?: RxRuntime } -) => { - const argRx = state<[number, Arg]>([0, undefined as any]) - const streamRx = readable | undefined>(function(get) { - const [counter, arg] = get(argRx) - if (counter === 0) { - return undefined - } - return f(arg, get) - }) - return writable, Arg>(function(get) { - const stream = get(streamRx) - if (stream === undefined) { +) => + makeFn(f, function(get, create) { + if (create._tag === "None") { return Result.initial() } return options?.runtime - ? makeStreamRuntime(get, (_) => stream, options.runtime) - : makeStream(get, (_) => stream as Stream.Stream) - }, function(ctx, arg) { - ctx.set(argRx, [ctx.get(argRx)[0] + 1, arg]) + ? makeStreamRuntime(get, create.value, options.runtime) + : makeStream(get, create.value as any) }) -} + /** * @since 1.0.0 * @category models