Skip to content

Conversation

@adamkopec
Copy link
Contributor

Hey,

during my daily work I find myself writing

.flatMap(something).map(__ -> null) or .flatMap(somethingElse).map(ignored -> fixedValue) way too often. this is an attempt to solve this issue :)

@adamkopec adamkopec requested a review from pivovarit as a code owner November 4, 2025 18:32
return map((ignored) -> val);
}

default Value<Void> voided() {
Copy link
Member

Choose a reason for hiding this comment

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

It's probably a bit too specific - with the other method, people can just write as(null) or with(null) and that's probably clearer than guessing what "voided" actually means

Copy link
Contributor

Choose a reason for hiding this comment

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

There are two advantages to using an explicit method: it clarifies the intent (which is good for code-reviews), and it avoids depending on type inference of the whole expression for the Void type.

For example, in our company we use a dedicated, Function<Object, Void> replaceWithVoid(), for this case as opposed to the <T> Function<Object, T> replaceWith(Supplier<? extends T> value) that we also have.

So, maybe with better naming there is a place for such a method?

Copy link
Member

Choose a reason for hiding this comment

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

This is a good point actually - you'd need to cast to Void to get the same semantics

Do you have an idea for a better name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

just a comment about the name, guys - I tried to follow the naming I'm the most familiar with, which is the one from cats' FunctorOps helper. there is an as(X) and void() there. in Java we can't do void, cause it's a keyword, but I'm happy to change it to whatever you suggest :)

Copy link
Contributor

@achinaou achinaou Nov 6, 2025

Choose a reason for hiding this comment

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

I’m also most familiar with the Typelevel/ZIO terminology of as and void/unit!

However, since Vavr’s main inspiration is Scala’s standard library with the terminology adapted to Java, I think the same strategy could apply here as well.

For developers coming from the Typelevel/ZIO ecosystems, .as and .voided would feel most familiar. But from the Scala stdlib perspective, and Vavr’s existing API, the .as* prefix conventionally signals a wrapper type conversion (e.g., List#asJava()), so reusing it for content replacement could break established intuition.

So, I think the methods .with(T) and .withVoid() are good choices as they build on the idea of "wither" methods (that may also come natively to Java), but without referring to a specific field, suggesting replacement of the Value’s content.

Copy link
Contributor

@achinaou achinaou Nov 7, 2025

Choose a reason for hiding this comment

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

Another not bad choice I think is the mapTo(T) / mapToVoid() option which is easily discoverable and cognitively closer to how someone would think about what would happen given an established intuition for map.

Copy link
Member

Choose a reason for hiding this comment

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

I think I like this option the most - as sounds like it's close to asJava() method family. Also, I think that alignment to Scala should have much lower priority than years ago.

@adamkopec what do you think about mapTo/mapToVoid ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's actually a very good idea, I updated the PR. @achinaou - you proposed something that is both easy to understand and not controversial. thx!

Copy link
Contributor

Choose a reason for hiding this comment

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

Really glad I could help!

@adamkopec adamkopec changed the title New feature: .as(U) and .voided() for Value<T> New feature: .mapTo(U) and .mapToVoid() for Value<T> Nov 7, 2025
assertThat(of(1).getOrNull()).isEqualTo(1);
}

// -- as
Copy link
Member

Choose a reason for hiding this comment

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

those are outdated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed 😅

assertThat(of(3).mapTo(2)).isEqualTo(of(1).map(ignored -> 2));
}

// -- voided
Copy link
Member

Choose a reason for hiding this comment

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

and this

let's update it for now, but I will eventually get rid of these comments and replace with nested junit test classes wherever it makes sense

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated both :)

@pivovarit pivovarit enabled auto-merge (squash) November 7, 2025 21:13
@pivovarit pivovarit self-requested a review November 7, 2025 21:13
@pivovarit pivovarit merged commit ea5afe3 into vavr-io:main Nov 7, 2025
8 checks passed
@achinaou
Copy link
Contributor

achinaou commented Nov 8, 2025

I think we missed one last thing. The methods mapTo and mapToVoid should be overridden for every subtype of Value that already overrides the map with a more specific return type (e.g., Try, Option, ...).

@pivovarit
Copy link
Member

Yes, good point @achinaou - we need to override them so that those methods return specific types instead of Value<Void>

CC @adamkopec

@adamkopec adamkopec deleted the feature/as-and-voided branch November 8, 2025 10:20
@adamkopec
Copy link
Contributor Author

Yes, good point @achinaou - we need to override them so that those methods return specific types instead of Value<Void>

CC @adamkopec

You're right, I added a PR.

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