# MutableRef

A `MutableRef<A>` is a small synchronous container for mutable state. It holds one
current value of type `A`, exposes it through `.current`, and offers pipeable
helpers for reading, replacing, and transforming the value **in place**.

Unlike [`Ref`](https://effect.plants.sh/state-management/ref/), every `MutableRef` operation is an
ordinary synchronous call — `get` returns the value directly, `set`/`update`
return the reference, and `getAndSet`/`updateAndGet` return the old or new value.
There is no `Effect` wrapping and nothing to `yield*`.

```ts
import { MutableRef } from "effect"

// `make` returns the reference directly — no Effect, no yield*.
const counter = MutableRef.make(0)

// Read with `get` (or just `.current`).
MutableRef.get(counter) // => 0

// `update` mutates in place and returns the same reference.
MutableRef.update(counter, (n) => n + 1)
MutableRef.get(counter) // => 1

// `set` replaces the value and also returns the reference.
MutableRef.set(counter, 10)

// `.current` is a plain readable/writable field.
counter.current // => 10
counter.current = 20
counter.current // => 20
```

## When to use MutableRef (vs Ref)

Reach for `MutableRef` when state is **local, single-fiber, and synchronous** —
a tight loop, a builder accumulating a result, an [`Inspectable`](https://effect.plants.sh/traits/) that
tracks a running count, or any place where you would otherwise reach for a plain
`let` but want a stable, pipeable handle you can pass around.

The moment state is **shared across fibers**, or you need updates to participate
in `Effect` composition, interruption, or fiber coordination, switch to
[`Ref`](https://effect.plants.sh/state-management/ref/) or
[`SynchronizedRef`](https://effect.plants.sh/state-management/synchronized-ref/). `MutableRef` updates are
plain imperative mutations: they are not atomic with respect to concurrent
fibers and do not return effects.
**Not fiber-safe:** `MutableRef` performs raw in-place mutation. Aliases to the same reference all
  observe the same changing value, and concurrent fibers can interleave their
  reads and writes. Use it only for local, single-fiber state.

A typical use is an accumulator inside a synchronous loop:

```ts
import { MutableRef } from "effect"

const sumTo = (n: number): number => {
  const total = MutableRef.make(0)
  for (let i = 1; i <= n; i++) {
    MutableRef.update(total, (t) => t + i)
  }
  return MutableRef.get(total)
}

sumTo(5) // => 15
```

## Naming conventions

Two consistent patterns run through the API:

- The `getAnd*` helpers (`getAndSet`, `getAndUpdate`, `getAndIncrement`,
  `getAndDecrement`) return the **previous** value.
- The `*AndGet` helpers (`setAndGet`, `updateAndGet`, `incrementAndGet`,
  `decrementAndGet`) return the **new** value.

Helpers that mutate without surfacing a value (`set`, `update`, `increment`,
`decrement`, `toggle`) return the `MutableRef` itself, so they can be chained or
piped.

Most binary operators are dual: you can call them data-first
(`MutableRef.set(ref, value)`) or data-last for piping
(`MutableRef.set(value)`). `MutableRef` also implements
[`Pipeable`](https://effect.plants.sh/traits/) and [`Inspectable`](https://effect.plants.sh/traits/), so it can be used with
`.pipe(...)` and prints cleanly via `JSON.stringify` / `Inspectable`.

## Reference

### make

Creates a new `MutableRef` initialized with the given value. `@category constructors`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make(42)
MutableRef.get(ref) // => 42

const config = MutableRef.make({ debug: false, timeout: 5000 })
MutableRef.get(config) // => { debug: false, timeout: 5000 }
```

### get

Reads the current value without mutating the reference. Equivalent to reading
`.current`. `@category general`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make("hello")
MutableRef.get(ref) // => "hello"
ref.current // => "hello"
```

### set

Replaces the current value and returns the **reference** (for chaining). Dual:
`set(ref, value)` or `set(value)`. `@category general`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make("initial")

const same = MutableRef.set(ref, "updated")
same === ref // => true
MutableRef.get(ref) // => "updated"

// Pipeable (data-last) form
ref.pipe(MutableRef.set("final"))
MutableRef.get(ref) // => "final"
```

### setAndGet

Replaces the current value and returns the **new** value. Dual. `@category general`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make("old")
MutableRef.setAndGet(ref, "new") // => "new"
MutableRef.get(ref) // => "new"
```

### getAndSet

Replaces the current value and returns the **previous** value. Dual.
`@category general`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make("old")
MutableRef.getAndSet(ref, "new") // => "old"
MutableRef.get(ref) // => "new"
```

### update

Applies `f` to the current value, stores the result, and returns the
**reference** (for chaining). Dual: `update(ref, f)` or `update(f)`.
`@category general`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)

const same = MutableRef.update(counter, (n) => n + 1)
same === counter // => true
MutableRef.get(counter) // => 6

// Updates do not clone — return a new value to avoid mutating in place
const user = MutableRef.make({ name: "Alice", age: 30 })
MutableRef.update(user, (u) => ({ ...u, age: u.age + 1 }))
MutableRef.get(user) // => { name: "Alice", age: 31 }
```

### updateAndGet

Applies `f` to the current value, stores the result, and returns the **new**
value. Dual. `@category general`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.updateAndGet(counter, (n) => n * 2) // => 10
MutableRef.get(counter) // => 10
```

### getAndUpdate

Applies `f` to the current value, stores the result, and returns the
**previous** value. Dual. `@category general`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.getAndUpdate(counter, (n) => n + 1) // => 5
MutableRef.get(counter) // => 6
```

### compareAndSet

Sets the value to `newValue` only if the current value equals `oldValue`,
returning `true` if it swapped and `false` otherwise. Comparison uses Effect's
[`Equal`](https://effect.plants.sh/traits/) semantics, not only JavaScript reference equality. Dual:
`compareAndSet(ref, oldValue, newValue)` or `compareAndSet(oldValue, newValue)`.
`@category general`

```ts
import { MutableRef } from "effect"

const ref = MutableRef.make("initial")

// Succeeds: current value matches the expected `oldValue`
MutableRef.compareAndSet(ref, "initial", "updated") // => true
MutableRef.get(ref) // => "updated"

// Fails: current value no longer matches — no change is made
MutableRef.compareAndSet(ref, "initial", "other") // => false
MutableRef.get(ref) // => "updated"
```

### increment

Adds `1` to a numeric reference in place and returns the **reference**.
`@category numeric`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.increment(counter)
MutableRef.get(counter) // => 6
```

### decrement

Subtracts `1` from a numeric reference in place and returns the **reference**.
`@category numeric`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.decrement(counter)
MutableRef.get(counter) // => 4
```

### incrementAndGet

Adds `1` to a numeric reference and returns the **new** value (pre-increment,
like `++i`). `@category numeric`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.incrementAndGet(counter) // => 6
```

### decrementAndGet

Subtracts `1` from a numeric reference and returns the **new** value.
`@category numeric`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.decrementAndGet(counter) // => 4
```

### getAndIncrement

Adds `1` to a numeric reference and returns the **previous** value
(post-increment, like `i++`). Handy for ID generation. `@category numeric`

```ts
import { MutableRef } from "effect"

const ids = MutableRef.make(0)
MutableRef.getAndIncrement(ids) // => 0
MutableRef.getAndIncrement(ids) // => 1
MutableRef.get(ids) // => 2
```

### getAndDecrement

Subtracts `1` from a numeric reference and returns the **previous** value.
`@category numeric`

```ts
import { MutableRef } from "effect"

const counter = MutableRef.make(5)
MutableRef.getAndDecrement(counter) // => 5
MutableRef.get(counter) // => 4
```

### toggle

Flips a boolean reference between `true` and `false` in place and returns the
**reference**. `@category boolean`

```ts
import { MutableRef } from "effect"

const flag = MutableRef.make(false)
MutableRef.toggle(flag)
MutableRef.get(flag) // => true
MutableRef.toggle(flag)
MutableRef.get(flag) // => false
```