Skip to content

Add AccumulateContext utilities for error accumulation in Arrow Core Context#3948

Open
nomisRev wants to merge 2 commits into
mainfrom
nomisrev/missing-accumulate-context-functions
Open

Add AccumulateContext utilities for error accumulation in Arrow Core Context#3948
nomisRev wants to merge 2 commits into
mainfrom
nomisrev/missing-accumulate-context-functions

Conversation

@nomisRev

@nomisRev nomisRev commented Jul 16, 2026

Copy link
Copy Markdown
Member

This PR adds context parameters support for Accumulate<A>. Currently I have this in my project:

@Suppress("DSL_MARKER_APPLIED_TO_WRONG_TARGET")
@OptIn(ExperimentalContracts::class)
@ExperimentalRaiseAccumulateApi
@RaiseDSL
@IgnorableReturnValue
context(raise: Accumulate<Error>)
inline fun <Error> ensureOrAccumulate(condition: Boolean, error: () -> Error): Value<Unit> {
    contract { callsInPlace(error, AT_MOST_ONCE) }
    return raise.ensureOrAccumulate(condition, error)
}

Such that I can write:

@IgnorableReturnValue
context(_: Accumulate<String>)
fun String.notBlank(): String = also { ensureOrAccumulate(isNotBlank()) { "Cannot be blank" } }

@nomisRev
nomisRev requested review from kyay10 and serras July 16, 2026 10:34
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Kover Report

File Coverage [0.00%]
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/context/AccumulateContext.kt 0.00%
Total Project Coverage 48.24%

@serras
serras force-pushed the nomisrev/missing-accumulate-context-functions branch from 53b423e to b54bf2f Compare July 17, 2026 18:18
@JvmName("accumulateContextMap")
context(raise: Accumulate<Error>)
@RaiseDSL
public inline fun <Error, A, B> Iterable<A>.mapOrAccumulate(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one. It has a different return type from the RaiseAccumulate overload.
There's definitely a use for it, just unsure about the name.

Accumulate is basically a delayed Raise (which lets it accumulate errors), so the convention usually is that XOrAccumulate methods return Value. mapOrAccumulate predates that conventino. It's ought to be called mapAccumulating like forEachAccumulating, but that's an annoying name change to go through.
(Maybe the opposite convention could work? and then forEachAccumulating is just the odd one out? All Value-returning functions are still experimental, so we could change them...)

mapOrAccumulate is a good name for this operation, but it means someone using RaiseAccumulate vs just Accumulate gets very different behavior. I suggest we leave it to another PR maybe?

@kyay10

kyay10 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Most of the utilities here have identical contextual bridges for RaiseAccumulate. Should we maybe remove the RaiseAccumulate ones, since RaiseAccumulate: Accumulate? I say remove because they're experimental, but we could of course add @Deprecated(HIDDEN) to them.

@nomisRev

nomisRev commented Jul 19, 2026

Copy link
Copy Markdown
Member Author

I say remove because they're experimental, but we could of course add @deprecated(HIDDEN) to them.

I would prefer @Deperecated(HIDDEN) to be honest, perhaps even with a proper deprecation cycle.
Experimental shouldn't mean we break binary perse but rather best effort.

mapOrAccumulate is a good name for this operation, but it means someone using RaiseAccumulate vs just Accumulate gets very different behavior. I suggest we leave it to another PR maybe?

Let's address in this PR. The different behavior is indeed strange. In terms of naming mapAccumulating is pretty good. Not sure if these names properly signal that mapOrAccumulate raises and mapAccumulating doesn't 🤔

cc\ @serras thoughts?

@kyay10

kyay10 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

perhaps even with a proper deprecation cycle.

Like not go to HIDDEN immediately? I don't think that would change much really. Source compatibility should stay the same, and other deprecation levels just means that the user will see the method deprecated, but won't be able to choose the Accumulate overload anyway, so it's just noise.

Or maybe you meant let's go HIDDEN and keep it for a few versions? Totally agree with that!

@nomisRev

Copy link
Copy Markdown
Member Author

Or maybe you meant let's go HIDDEN and keep it for a few versions? Totally agree with that!

Of course, you're right it's source compatible so just HIDDEN works fine👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants