Lambda expressions versus lambdaj
Asked Answered
I

2

7

During a Java integration project I did last year I discovered lambdaj and was immediately convinced by its ability to let me produce more readable code faster. I remember reading about lambda expressions coming to 1.8 around that time as well and thinking that I had found a plugin that already brought me all that functionality.

Now I'm revisiting lambda expressions and see that I may have been mistaken on lambdaj's purpose and scope. The way I see it now, lambdaj doesn't really offer lambda expressions but is rather a domain specific language designed to replace repetitive loops on collections. Its DSL syntax was made to look similar to anonymous functions and provides some of the same functionality such as closures and curried functions, but in the end it's limited by the JLS.

I'm now wondering what 1.8's lambda expressions can bring to a Java project that lambdaj can't. Is it just a matter of increased performance with native support for anonymous functions? Will expressions similar to lambdaj's collection manipulation functions be present in 1.8? Or are the lambda expressions in 1.8 meant for me to create my own anonymous functions. In that case, should a specific version of lambdaj be made for 1.8 that recreates the function library using real anonymous functions?

Imperialism answered 28/1, 2014 at 14:15 Comment(1)
You may find this talk - Lambda: A Peek Under the Hood - to be of interest.Venetian
R
8

lambdaj doesn't really offer lambda expressions

This is correct.

[lambdaj] provides some of the same functionality such as closures

If by this you mean "it provides closures"—no, it doesn't. A closure cannot exist without a lambda expression; it is actually a special case of a lambda expression, one which is the most demanding to implement.

Unfortunately, LambdaJ's project documentation is quite misleading in applying the term "closure" to something which doesn't qualify. An example from its Closures wiki page:

Closure println = closure(); { of(System.out).println(var(String.class)); }

The example is followed by this explanation:

In particular the var() method binds a free variable of type String to the closure.

That statement is simply false: there is no variable binding at all happening there, let alone a free variable. The construct results in something resembling a unary function, which expects a String argument. (Well, what it actually expects is an Object, but will fail at runtime if passed a non-String.)

On the other hand, the of() call in the example does go a bit in the direction of local variable capture. We might say that the argument passed to of() is captured by the object which it returns. However, we cannot refer to it in any further syntax; it is just the implicit target of the method call that follows. This is a far cry from full closures.

I'm wondering what 1.8's lambda expressions can bring to a Java project that lambdaj can't. Is it just a matter of increased performance with native support for anonymous functions?

Since LambdaJ doesn't provide the ability to write anonymous functions, the question is technically unanswerable. However, rest assured that Java 8's closures will outperform LambdaJ on a usecase-by-usecase basis because LambdaJ is fundamentally based on reflection, whereas Java's closures don't need it at all.

Will expressions similar to lambdaj's collection manipulation functions be present in 1.8?

Absolutely, and the support is very serious and complete. There are both more features, and the features are more composable. LamdaJ's capabilities are dwarfed by what is available out-of-the-box in Java 8. Check out the Streams API.

One of the primary design goals behind the Streams API was never even meant to be implemented by LambdaJ: the automatic parallelization of processing. Sure, FP-oriented collection processing looks nicer than the imperative idiom, but this is about much more than looks: it is a fundamental change. It is Java's bet on the future of computing, where the only way to boost performance will be to involve more parallel streams of processing.

Reprehend answered 28/1, 2014 at 16:49 Comment(3)
I'm very impressed by that Stream API. It does seem to be a tremendous leap forward for Java as a whole and makes lambdaj functionally obsolete in 1.8. I think that the project is still useful for pre-8 code that's heavy on collection manipulation but using those "closures" should probably be avoided.Imperialism
As I mentioned in my original answer here (downvoted and consequently deleted), my final verdict on LambdaJ was negative because, although it certainly made code more readable in the use cases it explicitly covers, there was no guarantee that your next use case would fit. The project ended up as a mixed-paradigm hodgepodge, some stuff handled in the FP style, other in the classical Java idiom. I prefer any one idiom to such hodgepodge :)Reprehend
BTW what I admired most in LambdaJ was the incredibly creative way to exploit Java Generics, reflection, bytecode generation, and invisible ThreadLocal-based links between lines of code to create an illusion of lambda expressions in the classical Java syntax.Reprehend
X
22

Forget lambdaj and start using Java 8 lambda expression asap!

Mario Fusco - lambdaj creator

Xeroderma answered 29/1, 2014 at 9:5 Comment(1)
That said, the lambdaj examples were useful in the design of the Collector framework!Teutonism
R
8

lambdaj doesn't really offer lambda expressions

This is correct.

[lambdaj] provides some of the same functionality such as closures

If by this you mean "it provides closures"—no, it doesn't. A closure cannot exist without a lambda expression; it is actually a special case of a lambda expression, one which is the most demanding to implement.

Unfortunately, LambdaJ's project documentation is quite misleading in applying the term "closure" to something which doesn't qualify. An example from its Closures wiki page:

Closure println = closure(); { of(System.out).println(var(String.class)); }

The example is followed by this explanation:

In particular the var() method binds a free variable of type String to the closure.

That statement is simply false: there is no variable binding at all happening there, let alone a free variable. The construct results in something resembling a unary function, which expects a String argument. (Well, what it actually expects is an Object, but will fail at runtime if passed a non-String.)

On the other hand, the of() call in the example does go a bit in the direction of local variable capture. We might say that the argument passed to of() is captured by the object which it returns. However, we cannot refer to it in any further syntax; it is just the implicit target of the method call that follows. This is a far cry from full closures.

I'm wondering what 1.8's lambda expressions can bring to a Java project that lambdaj can't. Is it just a matter of increased performance with native support for anonymous functions?

Since LambdaJ doesn't provide the ability to write anonymous functions, the question is technically unanswerable. However, rest assured that Java 8's closures will outperform LambdaJ on a usecase-by-usecase basis because LambdaJ is fundamentally based on reflection, whereas Java's closures don't need it at all.

Will expressions similar to lambdaj's collection manipulation functions be present in 1.8?

Absolutely, and the support is very serious and complete. There are both more features, and the features are more composable. LamdaJ's capabilities are dwarfed by what is available out-of-the-box in Java 8. Check out the Streams API.

One of the primary design goals behind the Streams API was never even meant to be implemented by LambdaJ: the automatic parallelization of processing. Sure, FP-oriented collection processing looks nicer than the imperative idiom, but this is about much more than looks: it is a fundamental change. It is Java's bet on the future of computing, where the only way to boost performance will be to involve more parallel streams of processing.

Reprehend answered 28/1, 2014 at 16:49 Comment(3)
I'm very impressed by that Stream API. It does seem to be a tremendous leap forward for Java as a whole and makes lambdaj functionally obsolete in 1.8. I think that the project is still useful for pre-8 code that's heavy on collection manipulation but using those "closures" should probably be avoided.Imperialism
As I mentioned in my original answer here (downvoted and consequently deleted), my final verdict on LambdaJ was negative because, although it certainly made code more readable in the use cases it explicitly covers, there was no guarantee that your next use case would fit. The project ended up as a mixed-paradigm hodgepodge, some stuff handled in the FP style, other in the classical Java idiom. I prefer any one idiom to such hodgepodge :)Reprehend
BTW what I admired most in LambdaJ was the incredibly creative way to exploit Java Generics, reflection, bytecode generation, and invisible ThreadLocal-based links between lines of code to create an illusion of lambda expressions in the classical Java syntax.Reprehend

© 2022 - 2024 — McMap. All rights reserved.