README.md

# smut

[![Package Version](https://img.shields.io/hexpm/v/smut)](https://hex.pm/packages/smut)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/smut/)

Dirty, dirty: Shared MUTable state.

Currently this package only supports the `erlang` target, but it'll support
`javascript` eventually.

Obviously, this isn't _really_ shared, mutable state in the way that can
cause undefined behavior. On the `erlang` target, state is stored in an
ETS table. Reads consult the table directly, but writes are governed by
an `Actor` to ensure that updates are "atomic". (That is, that no other
threads/tasks/processes can interfere with the value during or interrupt
the read-change-write compound operation involved in an update.)

The `javascript` target will behave similarly once it's supported.

This package is not in any way for the kinds of optimizations that can
be perpetrated by using mutable state; if you're here for that, you're using
the entirely wrong language. This package is for ergonomy in dealing with
things like rate limiters in web servers, where multiple threads of
execution all need to be counting requests together.

`smut` is still under heavy development. Obviously.

## Example

```gleam
import gleam/erlang/process
import smut

pub fn main() {
  let global_smut_table = smut.init()
  let assert Ok(val) = smut.new(global_smut_table, 0)

  let assert Ok(x) = smut.get(val)
  echo x
  // 0

  smut.set(3, val)
  // We sleep for a second here to give the write-governing process time
  // to make its update before reading back.
  process.sleep(100)
  let assert Ok(x) = smut.get(val)
  echo x
  // 3

  let assert Ok(x) = smut.update_and_get(
    fn(n) { n * 4 },
    val
  )
  echo x
  // 12

  let assert Ok(x) = smut.get_and_update(
    fn(n) { n - 3 },
    val
  )
  echo x
  // 12

  let assert Ok(x) = smut.get(val)
  echo x
  // 9
}
```