What's Stopping Me Using Java8 Lambdas – Try Debugging Them
rationaljava.com
rationaljava.com
Let me explain exactly what the issue is as there seems to have been a bit of confusion about my intentions.
I understand that by stepping into the lambda we are effectively stepping into a new frame analogous to 'stepping into a method' - therefore variables outside the frame will not be visible inside that frame.
But - if we are stepping into a for loop of sorts (or perhaps the lines() method of Files) - you do want to see the other variables in the enclosing method. And the point is that using the old constructs this is exactly what you were able to do.
Java is not functional enough (or at least the way I code isn't) that all the variables I need will be enclosed in the lambda.
In fact when you step into a lambda you retain the scope of the enclosing class (unlike an inner class), so for example when you call toString() you will be printing the toString() of the enclosing object. For this reason it makes sense that in the debugger you should not be considered to have stepped into a new frame when you drop into a lambda.
Ultimately this is all about usability and in real life I have found it extremely frustrating that I can't easily observe the values outside the lambda.
You know that the debugger can traverse the stack and show variables for the outer frames (assuming the lambda is invoked down-stack, as in your example), right? This is just a visualization issue of the debugger you're using and not a problem with lambdas themselves.
Javascript debuggers had to deal with this (the scope chain) for much longer, that's why variable views of JS debuggers show the whole scope chain instead of just the local frame.
No it's not - it's (apparently) a JDK issue. See the discussion in the Jetbrains bug report. BTW if Eclipse can do this, Jetbrains want to know.
If you have time, could you make the lambda a multi line chunk of code, so that it's clear that the breakpoint is inside the lambda? I'll pass it on to them. Thanks!
Of course this only works for cases where the debugger can tie the lambda used as method argument to another stack frame, i.e. it doesn't help with async invocations. But in async cases one cannot expect the JVM to lug around the whole stack frame from the time it was created, that could lead to memory leaks.
And from what I've gathered the Jetbrains bug may not talking about the same thing as the blog postis discussing. Their case is about a captured variable that gets inlined in some way that makes debugging difficult, OP is about inspecting arbitrary, non-captured variables in the debugger.
Consumer<U> has a single abstract method
void accept(U u)
The lambda effectively is an anonymous class implementing that interface / that single method. U resolves to ? super String. I.e. it expects a method that takes String or a superclass thereof as its first parameter.
That's what e is. It all gets automatically pieced together at compile time via type inference.
Lambdas are a nice way to reduce the boilerplate associated with anonymous inner classes, and that's about the limit of how I use them.
Then I realized that mutating variables is fairly common in a loop in procedural programming and that if you were to translate that to a forEach it would be useful to see what was going on.
I think the introduction of FP concepts in Java 8 is going to be interesting when it is not accompanied by immutability and other foundations in the language (or at least idiomatic usage like in Scala). I can't tell if that will cripple them or make them more accessible.
My concern is whether Java8 will spark a strong change in idiomatic usage or if it will just be another incremental change to the current status quo.
http://blogs.msdn.com/b/visualstudioalm/archive/2014/11/12/s...
However, one clear advantage of lambdas is that they reduce verbosity of anon classes.
Some people find the concision of lambdas helpful, so it's not necessarily a mistake.
Additionally, I feel that lambdas enable constructs that are much clearer and easier to reason about. Consider the case where you want to transform ever element in a list and produce a new list. Without the map function (which depends on lambdas) the logic wouldn't be that bad, you would create an empty list and append each element ad they are processed in a for loop. However, the intent of your code is less clear. Add in filtering and the intention of the code in your for loop ends up quite a bit harder to understand compared to a fairly straightforward select and map.
Your tools folks should be all over this. If they're not, switch tools.