Food for thought: `accumulate` dsl doesn't easily ...
# arrow-contributors
y
Food for thought:
accumulate
dsl doesn't easily allow you to "map" values:
Copy code
accumulate {
  val a by accumulating { raise(42) }
  val b by accumulating { a + 1 } // raises here
  println("Hello World") // this never runs
}
I don't know if there's really a way to get around this, at least right now with context parameters not being supported for property delegates. I'm not saying the behaviour is incorrect, either, but just that it'd be more helpful if it worked differently.
If we store the
RaiseAccumulate.Value
objects directly, then we maybe could do:
Copy code
accumulate {
  val a = accumulating { raise(42) }
  val b = accumulating { 
    a.bind() + 1 
  }
  println("Hello World")
}
context(_: Raise<RaiseAccumulate.Value<Nothing>>)
fun <T> RaiseAccumulate.Value<T>.bind(): T = when (this) {
  is RaiseAccumulate.Error -> raise(this)
  else -> value
}
I haven't thought through whether that's the right API to expose, though.
We could have
accumulating
simply delay all exceptions, similar to how
async
behaves. Maybe that's more correct? It'd be kinda surprising, and definitely a behaviour change:
Copy code
val someOuterRaise: Raise<Unit> = ...
accumulate {
  val a by accumulating { someOuterRaise.raise(Unit) }
  println("Hello World") // this currently never runs, but it would run under this "proposal"
} // this always raises to someOuterRaise, regardless of this proposal
This behaviour is true for
async
though. In some ways,
accumulating
is very similar to
async
, in fact, an
accumulatingAsync
would be nice to have, but that's besides the point.
If working on
Raise
has taught me anything, it's to be suspicious of any function of the form
Raise<T>.foo(..., block:  Raise<T>.(...) -> ...)
because it's giving special behaviour to only one
Raise
instance, when maybe you want to give that behaviour to many such instances. A similar situation showed up in the racing DSL, where the solution was to treat
RaiseCancellationException
in a special way.
accumulating
is a bit different though, since it doesn't actually take in a
Raise
, but rather an
Accumulate
.