| title | Understand Ref for Atomic State | ||||||
|---|---|---|---|---|---|---|---|
| id | data-ref | ||||||
| skillLevel | intermediate | ||||||
| applicationPatternId | core-concepts | ||||||
| summary | Use Ref<A> to model shared, mutable state in a concurrent environment, ensuring all updates are atomic and free of race conditions. | ||||||
| tags |
|
||||||
| rule |
|
||||||
| related |
|
||||||
| author | PaulJPhilp | ||||||
| lessonOrder | 6 |
Use the Ref<A> data type to model shared, mutable state in a concurrent environment.
Ref provides atomic, thread-safe operations for reading and updating state in effectful programs.
Managing shared state with plain variables or objects is unsafe in concurrent or asynchronous code.
Ref ensures all updates are atomic and free of race conditions, making your code robust and predictable.
import { Effect, Ref } from "effect";
// Create a Ref with an initial value
const makeCounter = Ref.make(0);
// Increment the counter atomically
const increment = makeCounter.pipe(
Effect.flatMap((counter) => Ref.update(counter, (n) => n + 1))
);
// Read the current value
const getValue = makeCounter.pipe(
Effect.flatMap((counter) => Ref.get(counter))
);
// Use Ref in a workflow
const program = Effect.gen(function* () {
const counter = yield* Ref.make(0);
yield* Ref.update(counter, (n) => n + 1);
const value = yield* Ref.get(counter);
yield* Effect.log(`Counter value: ${value}`);
});Explanation:
Refis an atomic, mutable reference for effectful and concurrent code.- All operations are safe, composable, and free of race conditions.
- Use
Reffor counters, caches, or any shared mutable state.
Using plain variables or objects for shared state in concurrent or async code, which can lead to race conditions, bugs, and unpredictable behavior.