and you'll have an immutable map that changes over time
p
and you'll have an immutable map that changes over time
👍 1
j
I was planning to use PersistentMap and then allow clients to get snapshots, then somehow feedback updates. But yes that will work great with Ref. The mutableMap was just a stand-in. Looking more at how to define an interface that reflects the semantics of how I expect the class to be used. Couldn't really find examples of how to embed IO in a class structure or what kinds of patterns are common. Everything in the docs consists of quite small examples to demonstrate a single concept. The list of applications that use arrow don't break it down by package (e.g. fx). In my case I wanted to express the factory should return an IO object, fail fast, but leave some discretion to the client. Wanted to avoid a situation where lifecycle is a hidden contract.. e.g. client has to load() explicitly after construction
p
IO
is not an architectural primitive, it’s a way of running
suspend
functions with concurrency, parallelism, cancellation etc
those projects use IO for some things
and here I show how I would write an IO-based backend service: https://www.pacoworks.com/2019/12/15/kotlin-coroutines-with-arrow-fx/
j
That was a great article. I'm still used to OOP way of writing code even after a year of clojure. I liked the way you set the context by framing fx as a compatible alternative to coroutines. Even the Jetbrains docs fail to differentiate use cases and mix coroutines, flows, actors etc in a single set of documents without enough context. So that brings me to the key question about IO and maybe I can articulate it better. When I do have something like my cache, should I be trying to keep IO out of the interface altogether? I see two alternatives: 1. Mark the invoke() function as
suspend
, call load() eagerly and return
Either<Throwable,ArchiveHashCache>
not wrapped in IO. 2. Return
Flow<ArchiveHashCache>
from invoke() but this has the disadvantage of allowing the client to construct multiple times via collect() and also doesn't really fit the intent. Flow would be a better fit for a subscription on cache events (new elements, deletions) Not for this portion specifically, but my App is intended to eventually run multiplatform, so I'm wary about having Arrow show up in the signature of my classes (this also applies to Either but that one is trivially replaceable)
p
Return
Flow<ArchiveHashCache>
from invoke() but this has the disadvantage of allowing the client to construct multiple times via collect()
can’t you just write a custom constructor for flows that loads the cached value on every subsequent subscription?
it’s just
Lazy
with an additional side-effect
invoke() function as
suspend
, call load() eagerly
so that’s the joke…suspend functions are always lazy because they won’t execute without an eager call kickstarting the whole chain
whether that call is blocking or async (
launch
in kx.coroutines) is just a detail for the caller