37 comments

[ 2.4 ms ] story [ 82.9 ms ] thread
Wouldn't this be better:

  private static final Log log = const Log.getLog("yo");
instead of all that rigmarole around ComputedConstants?
This proposal is trying to implement lazy evaluation without adding any new syntax. Your version would require a change to the parser, where this is just a new standard class.

A commenter above points out that there's a competing proposal that does introduce new syntax in the form of a `lazy` keyword:

https://news.ycombinator.com/item?id=36993023

The architects are wary about introducing new syntax into the Language. If it can be accomplished with an API, it should be done that way. Also, this keyword would probably use something like ComputedConstants in the background, and doing it this way would sweep that under the rug, which is also generally not how most Java features work. The delayed nature of this initialization is also not explicitly highlighted (unlike the lambda we would have to use with ComputedConstants), which will eventually bite people.
please for the love of gosling give us reasonable data structure literals nobody cares about this stuff i just want to be able to create a map or list w/o ceremony please
Perhaps you are using the wrong language. You should probably just stick with python or javascript where they just have simple lists and maps and pretty much nothing else.
A Java programmer feeling superior? Who would have though the day will come.

In all seriousness, this is grade school BS.

(a) Literals are a syntax improvement. Much more serious languages than Java have them.

(b) What Python and JS have don't amount to "simple lists and maps". They have the full gamut (including constructor based instantiation of different types).

(c) Literals don't have to be a single ("simple" or not) type. They can be whatever, and in Java these could include different classes of lists and maps initialized with the same literal syntax based on the assigned variable's type.

(d) When Oracle gives literals, Java programmers not familiar with them in other languages will suddenly love them too, and they'd not just be "for Python and Javascript" anymore.

You can build a named parameter+varargs based syntax on the JVM that is applicable to every container with the appropriate constructor.
Kotlin (which has very smooth interoperability with Java) makes it pretty easy:

  mapOf("a" to 1, "b" to 2)
...where "to" is actually an infix extension function that creates a Pair object, so there is no special syntax for maps.
Plenty of people care about native images/Project Leyden which this proposal is an integral part of.
Looks similar to the java.util.function.Supplier interface.
It's that, plus caching. It's basically what a thunk is called in Haskell land. You could also describe it as a Future, but with a vastly simplified API (no exceptions to catch when calling `get()`) thanks to being intended for the single-threaded case.
As far as I understood this is very much intended to be used in multi-threaded code as well. If you are sure that your object won't be called in multiple threads you can just do the simple "if(ref == null)" without locking and it should be reasonably fast - just not constant-foldable by the JVM.
The ComputedConstant indeed has to be threadsafe, but the proposal reads as its initializer would be executed on the thread of the caller of get(), and other callers would have to wait until initialization has completed. Indeed very useful for multithreaded programs as well.
It looks like this is going to be the Java version of Kotlin's lazy [0] and Scala's lazy val [1].

[0] https://kotlinlang.org/docs/delegated-properties.html#lazy-p...

[1] https://www.baeldung.com/scala/lazy-val

There were another JEP draft [1] recently that was proposing to introduce a lazy keyword for static fields. This new JEP looks like an alternative without any language change, and seems more likely to prevail.

[1] JEP draft: Lazy Static Final Fields - https://openjdk.org/jeps/8209964

Not quite. You need to have control over the JVM to do what this class does. The whole point of this class is a lazy value that interacts with the JIT in desirable ways.
Sure, but that's an (important) implementation detail. If this JEP is merged both Scala and Kotlin could implement their respective features in terms of ComputedConstant and get the performance enhancements for free.

Meaning it's semantically the same, with non-functional benefits.

[flagged]
Pros: maybe subjectively feels better for some people?

Cons: extremely painful amounts of churn for everyone

A ton of comments are missing the point of this complaining about list/map syntax etc. I'm not sure if the kotlin lazy addresses this.

The point is that static final variables interact especially well with the JIT's constant folding machinery. But lazy loading a constant necessitates that it can't be final: it's initially null until it's effectively final after the first lazy load. This finality is clear to the developer but not to the JVM.

This is introduces a way to implement lazy constants via a blessed class that solves this.

The article is pretty clear about what the point is — but does require some careful reading and context.

The example used is the venerable Logger class from the log4j package. It seem implausible that imprecise constant folding would cause a measurable performance decrease when using that class. So to me the point is not clear. A more convincing argument would be before and after stats of a benchmark showing x% performance increase.
Your other points aside, venerable might not be the right word for a package notorious for one of the most impactful zero days in recent memory.
Name seems a bit odd. The item it points at doesn’t have to be immutable. I’d rather something like LazyValue since Lazy is the important part.
Interesting article. For collections, I can see myself using these instead of static initialiser blocks. And TIL about the holder idiom. [1]

But for the love of Glob I wish web page authors would cease their contrast brinkmanship. Most of the text is barely discernible from the background.

[1] https://en.wikipedia.org/wiki/Initialization-on-demand_holde...

I get the idea, but the example itself about the logger is not great IMO.

Any class doing IO is a dependency, so you normally would just inject it via the constructor of the class.

This reminds me of 'sync.Once' from the Golang. Very nice to have this sort of functionality in the stdlib. Glad to see Java getting something similar.
What an awful text colour, had to do this just to read the article:

  $$('div, h1, h2').forEach(e => e.style.color = '#111')