https://www.cs.tufts.edu/~nr/cs257/archive/bill-pugh/jmm2.pd...
most other programming languages make excuses. Build system with dependency resolution that works (unlike Python) IDEs take advantage of static nature of language. Static nature of language enables refactoring.
Lambda syntax that's probably more concise than your favorite language. Implementation of Lambdas that meshes perfectly with existing practices in Java. All-virtual polymorphism is one of many ways that Java doesn't steal IQ points from you the way C#, C++ and languages like that do.
Thing is, they turned it around.
Some APIs were excessively verbose due to the lack of lambdas, which were emulated using anonymous inner classes.
If you have a link, please share.
Gosling say closures represent the realization of a dream that was postponed in Java's early days and resulted in the invention of inner classes - "an uncomfortable compromise" that failed to provide the desired level of simplification. He notes criticism that closures are too complex, but advises people to read "through all of what Neal has written".
Java is mostly about interfaces. Classes are just a way to implement them. This is one of the differences between Java and C/C++.
The way lambdas bind to SAM interfaces and implement them is pretty different than say scala or even C/C++ function pointers where the necessary parameter/return type can be encoded into a variables type and referred to directly.
I think that's cool enough but one of the subtle elements of design brilliance was how local variables must be final to be bound into a closure. There's a whole class of ambiguity removed and static guarantees in the face of concurrency that I think goes unappreciated.
I'll have to mull over that. I guess to me they seem aligned enough, thats why it feels so elegant. Or maybe I haven't thought about it enough.
> rather compiled as static functions and an invokedynamic instruction that will resolve to them at first occurrence
Yea! but that invokedynamic calls the lambda metafactory which spins up bytecode for a class with 2 things: a) a constructor to bind the values captured from the scope the lambda was declared in to fields, and b) an instance method that feeds those fields to the static function you referred to.
I'd argue that that class is essentially an anonymous class. Maybe I'm easily impressed, but that functional programming <-> OOP duality of lambdas/closures and SAM interfaces always felt profound.
We can get along! There's no need for this feud!
This library contains a huge number of Iterables, each of which has at least one Iterator implementation.
https://github.com/paulhoule/pidove
It is convenient to let the Iterator be immutable and the Iterator be an inner class that gets its configuration information out of the Iterable.
(That said, if people really thought seriously about Iterator being a Supplier<Iterable> people might think more rationally about error handling. Also in a slightly parallel universe the Iterator would only have one method since remove() hardly ever gets used and having both hasNext() and next() methods is asking for bugs.)
This is how things like Babashka (Clojure CLI scripting runtime) are possible [0]
It's even possible to compile it ahead of time, making projects like a Clojure CLI scripting runtime with almost instant startup time possible (babashka).