[External] : Re: Feedback about LazyConstants API (JEP526)
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Dec 9 14:23:22 UTC 2025
I believe there is definitively possible overthinking at play here.
Some notes:
* in any case, we have at least _two_ primitives (either orElse + get,
or tryGet + get). That's because one primitives triggers initialization,
the other doesn't.
* orElse is similar to what we do in ScopedValue. There's not many other
APIs that do this.
* creating an optional is more expensive -- but with Valhalla costs will
likely go down and be comparable
* returning an Optional might also be confusing because the Optional is
a _snapshot_ at some point in the lifecycle of the lazy constant -- e.g.
you can get an empty optional with tryGet(), then call get(). Now the
previously returned optional is not in sync with the lazy constant (not
sure how much this is a concern -- but listing it here as a possible
element of confusion)
* in all possible worlds, it seems that `isInitialized` can be derived,
either from orElse, or from tryGet. That said, for a construct called
LazyConstant, I think asking whether the constant is initialized or not
seems a good method to have, and can also be used to explain some of the
behavior of the API (e.g. in the javadoc). So I'm not sure I'd be ok
with going the full way and drop it.
Given all this, possible way forwards would be:
1. keep everything as is (after all, we got here for a reason)
2. drop orElse, and keep just get/isInitialzied (on the basis that the
internal optimization of orElse is not really worth it. We can also
always add it at a later point compatibly)
3. drop orElse and replace it with tryGet or some Optional-returning
equivalent
I don't have strong opinions on either of these. Perhaps, the "if in
doubt leave it out" angle should win (2).
Maurizio
On 09/12/2025 14:12, Anatoly Kupriyanov wrote:
> My idea is not an optional /interface/, but an interface for something
> which is convertible to the Optional /type/. In other words, neither
> the LazyConstant nor to ScopedVariable *is not* an optional itself,
> but could be converted to it uniformly.
> Something like this:
>
> interface Optionable<T> {// need to think about the better naming!
> T orElse(T other);
>
> // and maybe even:
> default Optional<T> asOptional() {
> return Optional.ofNullable(this.orElse(null));
> };
> }
>
> and then LazyConstant, ScopedVariable, etc could just implement the
> interface to unify on the notion of "return a user-provided value
> if some condition isn't met". Sounds like a decent path to abolish nulls.
>
> But I feel I am overthinking this...
>
>
> On Tue, 9 Dec 2025 at 13:35, Red IO <redio.development at gmail.com> wrote:
>
> I initially thought I agree with your statement that orElse is a
> common pattern in the jdk. But then I failed to come up with a
> second example. I then searched the jdk github repo for the
> method. And I only found Optional and it's specializations and
> ClassHierarchyResolver.
> So I would suggest yes, it's an often used method ... of the
> Optional class. Not many apis seem to expose it. The case of
> exposing an accessor that returns an Optional on the other hand is
> incredibly common across the jdk. This is exactly the case
> Optional was designed for. In this sense Optional is the
> "Interface" you are suggesting.
>
> My main argument against reusing orElse here is that the context
> is a completely different one.
> An Optional orElse method is a pure function that always returns
> the same value. It signals that the value is not there.
> LazyConstant is different in this regard. The LazyConstant orElse
> is not pure at all. It depends on rather someone else already
> initialized the value or not. It signals that the value is not
> there YET.
>
> Great regards
> RedIODev
>
>
>
> On Tue, Dec 9, 2025, 13:51 Anatoly Kupriyanov <kan.izh at gmail.com>
> wrote:
>
> Right, the ScopedValue is another good example I've forgotten.
> In that case I am even more inclined to keep the `orElse` as
> it looks like a repeating pattern across JDK libraries.
> Consistency is the way to go!
> And maybe even consider having a new interface for the method
> to make this pattern explicit?..
>
> I am glad that `orElseSet` is removed, the side-effecting is
> bad; also in other parts of JDK we already have
> `computeIfAbsent` for the same idea. I did not hear about it,
> and yeah, sounds like the source of this confusion.
>
>
> On Tue, 9 Dec 2025 at 12:05, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>
>
> On 09/12/2025 11:59, Anatoly Kupriyanov wrote:
> > To be honest, I don't really see why this method causes
> such confusion.
>
> In part I agree. E.g. when we added this, what we had in
> mind was just
>
> https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/ScopedValue.html#orElse(T)
>
> E.g. other APIs have `orElse` method that return a
> user-provided value
> if some condition isn't met.
>
> I believe the problem we're discussing here is likely also
> related to
> the fact that the API used to have a side-effecting
> `orElseSet`, which
> is now removed, and I wonder if, because of that, folks
> are reading too
> much into what orElse does?
>
> Maurizio
>
>
>
> --
> WBR, Anatoly.
>
>
>
> --
> WBR, Anatoly.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20251209/c977e9fd/attachment.htm>
More information about the amber-dev
mailing list