Effect CommunityEC
Effect Communityβ€’3y agoβ€’
17 replies
whatplan

Understanding the Return Type of `Ref` Get Methods

I'm struggling to understand why the Ref get functions return a T (Effect<never, never, T>) and not a Readonly<T>.

Isn't the whole point of a Ref to only allow mutation through the ref itself, and only provide an immutable view into what's inside?

The docs say:

"In traditional imperative programming, one common way to store state is using variables. However, this approach can introduce bugs, especially when the state is shared between multiple components or functions."

"With Ref, we can share state between different parts of our program without relying on mutable variables directly. Instead, Ref provides a controlled way to handle mutable state and safely update it in a concurrent environment."

But currently Ref is really no different than just passing around a { current: T } variable that anyone can mutate at anytime:

const program = Effect.gen(function* (_) {
  const ref = yield* _(
    Ref.make({
      foo: 0,
    })
  );

  yield* _(
    Ref.update(ref, (n) => {
      n.foo += 1;
      return n;
    })
  );
  // your *supposed* to only update like this

  const value = yield* _(Ref.get(ref));
  value.foo += 1;
  // but nothing stops you from just getting the value and mutating it
  
  yield* _(Console.log(value.foo)); // 2
});


I would expect MutableRef to have this behavior, becuase its 'Mutable', but when you look at the type signatures between MutableRef and Ref they are identical (except Ref makes them Effects)

But to me that doesn't make a lot of sense, shouldn't the '(Immutable)Ref' only give you a immutable value of what's inside?

Maybe I am missing something, any help understanding this is appreciated
Was this page helpful?