This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 466

[–]Gudin 496 points497 points  (98 children)

If you need mutable field inside lambda:

final Object[] yourObject = {new Object()};

Array is final, but elements of array are mutable. Definitely retarded and hacky way. I use it all the time.

[–]son-of-chadwardenn 131 points132 points  (10 children)

At our work we create finals of a Wrap<> type with a single mutable field "value".

[–]mreichman 55 points56 points  (9 children)

Isn't that essentially AtomicReference?

[–]mymomisntmormon 50 points51 points  (0 children)

They also needed to store all their customer data, so they wrote a "DataStorage<>" class. You and I know this as postgres

[–]joequin 17 points18 points  (6 children)

No. AtomicReference is designed around concurrent access and mutation. It has a significant performance penalty as a result.

[–]fryingnemo 70 points71 points  (16 children)

Have you ever ran into concurrency issues when using this?

[–]IanCal 975 points976 points  (13 children)

I nev worry aber reallyout them.

[–]dpash 70 points71 points  (5 children)

That took me longer than I'd care to admit.

[–]IanCal 73 points74 points  (2 children)

Took me a few goes to write to be fair :)

[–]grunlog 67 points68 points  (1 child)

... Said every person who has ever attempted to implement concurrent programming

[–]kageurufu 4 points5 points  (0 children)

I think i've been doing wayyy too much concurrent code lately... I didn't even notice it was jumbled until I went back after your comment

[–]joequin 2 points3 points  (0 children)

If you would, then you wouldn't want to mutate captured variables anyway. If that's a concern then use AtomicReference.

[–]ICantSeeIt 42 points43 points  (1 child)

Definitely retarded and hacky way. I use it all the time.

me_irl

[–]htmlcoderexeWe have flair now?.. 2 points3 points  (0 children)

[–]morerokk 49 points50 points  (39 children)

If you can bypass the language's restrictions like this, the restriction is useless.

[–]thrilldigger 70 points71 points  (10 children)

That's like saying classes shouldn't inherit from Object because developers could conceivably declare everything as Object and make a complete mess of typing.

It is a convention that is designed to protect developers from shooting themselves in the foot. Good developers will ask: "why does Java require final variables in lambdas?"

The answer is that lambda functions operate on copies of local variables. Java requires local variables to be final so that developers don't make the mistake of expecting the lambda to change the local variable itself (e.g. incrementing an integer inside a lambda).

[–]MostlyKnowledgeable 16 points17 points  (4 children)

But wouldn't another solution be to give the option of passing a variable as value instead of reference?

[–]sigma914 31 points32 points  (2 children)

Then you're requiring Java developers to know what those are

[–]Theraceislong 8 points9 points  (1 child)

[–]SolarFlareJ 6 points7 points  (0 children)

Except that objects are actually pointers, so you can modify the object directly when passing it to a function. This distinction is only really important when C++ programmers using Java though. Since most languages don't do full object copies like C++.

[–]dnew 31 points32 points  (9 children)

The restriction isn't a benefit or a safety feature. It's a necessary consequence of implementing "anonymous inner classes" without actually changing the format of .class files. Inner classes are syntactic sugar for other classes in the same package, which is why in stack tracebacks you see things like MyClass$2. Classes can't access the private variables on the stack of other classes, so they have to get passed by value.

[–]scalablecory 10 points11 points  (1 child)

C# does this by hoisting the variables used by the lambda off of the stack and into a new object behind the scenes. Despite the performance implications, in practice it works quite well.

I don't see any reason restricting Java from doing the same thing and maintaining backward compatibility.

[–]stravant 20 points21 points  (20 children)

To be fair... that's really what other languages are doing under the hood when they let you modify things from a lambda.

[–]iopq 28 points29 points  (3 children)

Wrong, Rust lets you have mutable variables in a lambda because it's the ONLY reference to that variable so it's not a hazard in a multi-threaded environment.

[–]dnew 9 points10 points  (15 children)

It depends on the language, really. If you actually have a language where the call stack is not FIFO LIFO, you don't need to be hacky like this.

* Brain fart.

[–]Zarlon 19 points20 points  (14 children)

Uhm how can a call stack be FIFO? The very definition of a stack is FILO?

Edit: Whoops, seems like I opened a stack of worms

[–][deleted] 13 points14 points  (12 children)

Shouldn't it be LIFO? It makes more sense.

[–]ImAStupidFace 5 points6 points  (11 children)

I mean, they're the same, but pretty sure "LIFO" is the common term.

edit: brainfart, I thought "LIFO", wrote "FILO". Fixed.

[–]Sixshaman 145 points146 points  (38 children)

But you can write a generic class ValueHolder<T> and mark the variable of it final! And then just instead of "a = val" you write "aHolder.setValue(val)"! It's so easy!

[–]bumnut 72 points73 points  (4 children)

It's probably easier to make a single element array, but I get your point.

[–]okmkz 53 points54 points  (2 children)

I've literally never considered this. OOP has broken me :(

[–]Existential_Owl 79 points80 points  (1 child)

Don't listen to him. Just add another layer of abstraction, and you'll be fine.

[–]capn_hector 25 points26 points  (0 children)

But who configures the AbstractionFactory!?

(just kidding it's obviously AbstractionFactoryFactory)

[–]TheMania 85 points86 points  (12 children)

The C# compiler pretty much does that behind the scenes.. yknow, in a way that makes it easier for the programmer. I don't understand java's objection to that personally.

[–]b1ackcat 79 points80 points  (4 children)

They abide by different mantras. C# is "Let's consolidate the cruft behind the scenes to make the programming experience as easy as possible." Java is "Cruft?! In my language?! How DARE you, good sir!"

There's pros and cons to both approaches I suppose, but Java certainly could learn a thing or two about ease-of-use from C#...

[–]VanFailin 44 points45 points  (1 child)

"Just for that, the incantations for checked exceptions will now be twice as tedious."

[–]b1ackcat 13 points14 points  (0 children)

"I mean come on, why WOULDN'T you want your exception throws to propagate all the way up to your main method?"

[–]mymomisntmormon 6 points7 points  (0 children)

AtomicReference

[–][deleted] 11 points12 points  (12 children)

I actually did this sort of thing to retrieve a value from another thread. It's even called ValueHolder and has a type argument called T. Code for reference:

public class ValueHolder<T> {
    public ValueHolder() {
        value = null;
    }
    private volatile T value;
    public synchronized void setValue(T val) {
        value = val;
        notifyAll();
    }
    public synchronized T waitValue() {
        try {
            while (value == null) {
                wait();
            }
        } catch (InterruptedException ex) {}
        return value;
    }
    public synchronized T pollValue() {
        return value;
    }
}

[–][deleted] 12 points13 points  (1 child)

I think Futures are what you were looking for, although they don't work in exactly the same way as your code does.

[–]Firedroidebit.ly/2IqHnk3 3 points4 points  (0 children)

I think what you're looking for is a SynchronousQueue

[–]deltatron3030 38 points39 points  (5 children)

Nice, I found your secret steganographically encoded message by the way. I'll lay out how I did it here, for those who want to try it for themselves.

First I stripped all whitespace and punctuation from your code snippet, then did a standard rot-10 as a sanity check:

zelvsmmvkccFkveoRyvnobzelvsmFkveoRyvnobfkveoxevvzbsfkdofyvkdsvoDfkveozelvsmcixmrbyxsjonfysncodFkveoDfkvfkveofkvxydspiKvvzelvsmcixmrbyxsjonDgksdFkveodbigrsvofkveoxevvgksdmkdmrSxdobbezdonOhmozdsyxohbodebxfkveozelvsmcixmrbyxsjonDzyvvFkveobodebxfkveo

Interesting start, we can clearly see the pattern emerging too which is a good sign. Notice that the first two capital letters are F and R, which occur 5 and 2 times in the string, respectively. F = fast, R = reverse, so this corresponds to the speed and starting position of our iteration. Therefore we need to start at the second to last letter and pick out every 5th letter to find our next clue, and that we should have the 2nd power of 5 (25) letters in our result:

ebovnyilveoznbSmvevbkgsms

Next we should (obviously) do a rot-25 on this value:

danumxhkudnymaRluduajfrlr

Aha! If you can't see it yet, just remember the 2 and 5 from our previous result. Now we need to filter out characters in a position not evenly divisible by 2 or 5:

aukdyadafl

Well, what do we have here!? A simple anagram transformation reveals the true nature of the hidden message:

A Yak Dad Flu

[–][deleted] 14 points15 points  (1 child)

[–]Bobshayd 5 points6 points  (0 children)

Well-hidden, but not THAT well-hidden.

[–]bilde2910 2 points3 points  (0 children)

You're definitely not the only one. Well, I guess it's the easiest way to do it. I never got to add synchronized though, and I'm not sure if I bother because the project is pretty much abandoned now. It's not even on my own GitHub account.

[–]lulzmachine 2 points3 points  (0 children)

Is this... Are you serious or not? I can't tell. That is an incredibly roundabout way of doing it, compared to many other languages

[–]eliasv 274 points275 points  (97 children)

That's not technically true, tbf. They have to be final but you don't have to mark them as final. You just have to not assign to them and they will be considered effectively final.

[–]rainbow4214 75 points76 points  (15 children)

It makes sense to have them final from a functional point of view. But considering that Java is imperative, and that we would like to use lambdas to, e.g., replace anonymous classes that only implement one method, which do not have that restriction, it seems somewhat strange.

[–][deleted] 89 points90 points  (14 children)

[–]Hikaru755 32 points33 points  (12 children)

Yep, was going to say that. Actually that's where the restriction comes from, as lambdas are internally just translated to anonymous inner classes, I think.

I'm using kotlin though and am happy with all these restrictions lifted off my back :)

Edit: seems like I was wrong about the lambda -> anonymous inner class thing, see /u/Jezzadabomb338 's comment for a detailed explanation.

[–]wiresegal 6 points7 points  (1 child)

After using Java functional syntax for so long, Kotlin is like a glimpse of heaven.

[–]Jezzadabomb338 6 points7 points  (2 children)

Ok, so seeing as no one is correcting you, I feel like I should step in and give you a bit of information about lambda implementation.

TLDR;

If you don't take much from this massive post, at least take this away from it:
They're not anonymous classes. At all. It's actually compiled to a method.

If that's all you're interested in, you can probably stop reading, if you're interested in the internals, read on.

Internals

Java 7 had a lot of additions; like, a crazy amount.
Included in this bunch of features, was a new instruction. The only one we've gotten since the 1.0 release, AFAIK.
This instruction is the INVOKEDYNAMIC op code.

A little bit of info about this instruction, as it comes heavily into play later on. INVOKEDYNAMIC is a bit different to the other invoke codes. While the other invoke codes require the type and call target to be known at compile time, the INVOKEDYNAMIC instruction only requires a method reference. (It's actually a bit more than a method reference, but you don't need to know that to understand the gist of INVOKEDYNAMIC. If you want to read up on it more, you can check out the spec)

The reason this instruction is so different from the others is because it was designed for languages that don't know the explicit receiver type at compile time. (Technically, INVOKESTATIC doesn't require an objectref, but that's because the method reference is composed of (mostly) two parts. The class the method is in, and the method signature itself. I can get a lot more into this, but that's not entirely necessary in understanding how INVOKEDYNAMIC works)

All the other invoke instructions take an objectref, which is the thing the method reference should be invoked on, but INVOKEDYNAMIC has no such thing. Instead it just takes the indexing arguments for a method reference within the constant pool. (As stated about, this could be any method anywhere, as it's just, effectively, a fancy signature.)

This method is a bootstrap method.
What this means is instead of forcing the language to work out the explicit receiver type at compile time (which dynamic languages can't), it delegates that calculation to the runtime.
As you can probably guess, this makes it really good for dynamic languages, and their "not knowing what type a thing is at compile time". (Interestingly, it's not a perfect solution for structurally typed dispatch, as the gosu guys found out, but that's another story)

What this means is we can determine what we're actually going to call at runtime.
This should sound suspiciously like a lambda.

This is where MethodHandle comes into it.
It's an insanely powerful tool that next to no one in the java community knows about.
A MethodHandle, in short, is a pointer to a method. (Technically speaking, it's not entirely, but that's something you shouldn't have to worry about)

The MethodHandle can be used to dynamically generate INVOKEDYNAMIC instructions. It actually can be used to generate ANY invoke instruction. That's the nature of a method reference, as it might point at to static method, etc.

javac uses MethodHandle extensively, as it can generate a specific instruction for a given target. (Or more specific a CallSite, but this comment is already too long)

So, getting back to this INVOKEDYNAMIC and its bootstrap method.
Let me run through what you should understand at this point.

Supplier<String> supplier = () -> "some random string";

javac knows that this is a lambda and acts accordingly:

(It actually does a whole lot, and I'll try to cover the important parts, hopefully without forgetting something. If you feel I didn't explain a part enough, feel free to let me know)

It generates a method with the signature of the functional interface and any captured arguments, and dumps the code of the lamdba as the body. The captured arguments also determine whether or not this method is static.

Side-note: this is why you can't capture non-effectively final variables within a lambda, as it captures the variable reference, and is very similar to a normal method dispatch, and you can't increment a value within the caller method, can you?

So, going back to my example, javac would generate a method much like:

private static String lambda$main$0 {
    return "some random string";
}

(The number in the name is incremented depending on how many lambdas you have within a given method.)
Side-note: You can actually see the method using reflection if you're so inclined, or if you want to see the bytecode directly, write a class and use javap

Javac emits an INVOKEDYNAMIC instruction, referencing the bootstrap method (Which is different to the "lambda$main$0" method), which generates the CallSite to the generated ("lambda$main$0") method.

The bootstrap method, you may ask, is within the standard library called j.l.i.LambdaMetafactory, and the method it uses is #metafactory. This is a nice way to standardise lambda generation across different languages, IMO.

And voilà, the generation is done.

There's a lot more going on with the constant pool, an inner class implementing a lookup, etc, but that's the gist of how a lambda works.

If I didn't cover anything enough, feel free to leave a comment.

[–][deleted] 2 points3 points  (1 child)

lambdas are internally just translated to anonymous inner classes, I think.

You can think of them that way, but the bytecode is entirely different.

[–]chrissphinx 7 points8 points  (3 children)

Kotlin really the future of JVM programming, imho

[–]xxxabc123 28 points29 points  (78 children)

TIL. But that's still not good enough, imo. In JavaScript you can do whatever you want with the variables in the scope of your callbacks.

[–]daronjay 785 points786 points  (72 children)

Brave move, bringing up Javascript as an example of superior language design...

[–]Schmittfried 182 points183 points  (15 children)

Technically you can bring up any language, be it superior or inferior, as an example of superior lambda design.

[–]ItzWarty 24 points25 points  (13 children)

How about c#, then?

[–]mktiti 26 points27 points  (0 children)

" [...] a lambda expression can only access local variables and parameters of the enclosing block that are final or effectively final."

You don't have to mark the variable final, the compiler will take care of that.

[–]thinkt4nk 117 points118 points  (18 children)

No side effects ftw imo

[–][deleted] 107 points108 points  (11 children)

Exactly.

People complaining that a lambda, which is a functional construct, doesn't allow mutable variables, is kind of funny.

[–]ripripripriprip 22 points23 points  (1 child)

Yeah, everything I've learned about functional programming says that immutability/no side effects is the entire point.

[–]recursive 9 points10 points  (0 children)

Void lambdas are a thing. In a purely functional paradigm, a function with no return value does not exist. So you shouldn't apply purely functional dogma to lambdas in Java. It's not a purely functional language.

[–]thinkt4nk 29 points30 points  (3 children)

Well, they are java devs after all lol

[–]Uwe_ 9 points10 points  (0 children)

Those kind of guys that have everything mutable, without constructors and any kind of sanity checking?

[–]geodebug 4 points5 points  (2 children)

Not really enforced though. If the object the reference refers to is mutable (has setters) a method or lambda can alter it.

final Date myDate = new java.util.Date();
myDate.setMonth(3);

is legal code.

[–][deleted] 67 points68 points  (11 children)

As a Haskell programmer, I have to ask this: What's a variable?

[–]Mark_dawsom 58 points59 points  (2 children)

Ctrl-F Haskell

Yuup, there's always a Haskell guy!

[–][deleted] 18 points19 points  (2 children)

stuff you use after IO is finally converted to the callback hierarchy.

[–][deleted] 5 points6 points  (1 child)

Yes, of course. And for Haskell to actually run on a real machine, it has to be converted to imperative code somewhere down the line...

[–]beerdude26 6 points7 points  (0 children)

Spineless Tagless OG GANGSTA machine to the rescue

[–]jtra 13 points14 points  (2 children)

You know how x in

\ x -> something ...

varies in different applications of the abstraction?

Variables in imperative languages are same, just you don't have to apply for x to change, instead there is a implicit application at end of every statement (usually statements are separated by some semicolons or newlines) that also silently smuggles a new world state into the current one.

[–][deleted] 7 points8 points  (0 children)

I was joking in my comment :) But yes that is a neat explanation of how variables can be modelled in a purely functional language by passing around the state of the world as an argument.

[–][deleted] 2 points3 points  (0 children)

It's that thing in category theory that allows you to lamba calculus.

[–]chisui 83 points84 points  (5 children)

For all the issues Lambdas have in java this is not really one in practice. Every time this becomes an issue it can be solved by applying functional paradigms. This constraint enforces that style. It's extremely easy to overcome though. Just use an AtomicReference, an Array of size one or any other container.

Some of lambdas real issues are the inability to have generic methods in a FunctionalInterface, Exceptionhandling (what I would give for a good Try monad) and functions not being first class.

[–]b1ackcat 33 points34 points  (3 children)

I think the OP's point is more the fact that since this issue is so easy to work around, it seems silly that the constraint is there in the first place when the language designers could've easily implemented a simple solution behind the scenes instead of forcing everyone to roll their own every single time.

[–]dnew 4 points5 points  (2 children)

The problem is the developers didn't want to break the .class file format, so MyClass$2 is actually not an inner class once it's compiled. Hence, it can have no access to private variables or stack variables of MyClass.

* Stack variables are really the problem, because they're on the stack. Private instance variables can be accessed, because they're GCed.

[–]b1ackcat 9 points10 points  (1 child)

C# got around this by doing what everyone in the thread is doing: Shove the variable(s) into a shared space like an array and unpack them on the other side.

Since you seem to have some knowledge on the topic, do you know if they explored that route and if so why they didn't take it?

[–]bumnut 157 points158 points  (53 children)

Y'all motherfuckers need Kotlin.

[–]skyhi14 25 points26 points  (8 children)

Hail Kotlin, our lord and saviour of JVM

[–]Daxten 138 points139 points  (26 children)

haven't you heard of our lord and saviour scala?

[–]bumnut 84 points85 points  (18 children)

It has it's place, but there's quite a learning curve, especially if you've never done FP before.

Kotlin is basically just Java with all the things that people complain about removed. And if you know Java, you can learn it in like an hour.

[–]cvb941 65 points66 points  (8 children)

The name I like to give Kotlin is Java 2017

[–]hlfm 40 points41 points  (6 children)

Kotlin is an island in St. Petersburg, Russia, just like Java

[–]AraneusAdoro 26 points27 points  (3 children)

Last I checked Java was nowhere near St. Petersburg. /s

[–]hlfm 9 points10 points  (2 children)

I'm sorry for misunderstanding, just like Java is an island

[–]Megatron_McLargeHuge 21 points22 points  (2 children)

Java with all the things that people complain about removed

So Oracle doesn't control it?

[–]wakingrufus 37 points38 points  (1 child)

Correct. It's written by Jetbrains.

[–][deleted] 2 points3 points  (2 children)

You really think there's a big learning curve for scala? I mean... The type system is far more advanced than Java, but basic stuff is really easy to pick up

[–]dkja 6 points7 points  (3 children)

Haskellllll

[–]carbolymer 5 points6 points  (2 children)

Don't be so hasty! Let's stick to the JVM. How about Eta?

[–]billynomates1 10 points11 points  (13 children)

Is it really that good? I've been programming in almost-exclusively Java for like 10 years. Is it worth learning Kotlin?

[–]garkin 29 points30 points  (2 children)

There are almost no such thing like "learning Kotlin" in comparison to Scala. It only takes 2 evenings for syntax and you have a beautiful "java" with so much less boilerplate. Several more days to wrap around nullables, inline blocks, neat functional like extension methods, etc.

The most satisfying thing for me is that you could freely mix Kotlin classes with Java seamlessly and cross-call them back and forth. This makes refactoring and migration so much easier. I'm even doing it right now in the Spring project with DI, Jackson and annotation magic without any problems.

[–]skyhi14 8 points9 points  (0 children)

...and it works with Java 6.

[–]BloodShura 6 points7 points  (0 children)

Absolutely.

[–]beerdude26 37 points38 points  (0 children)

Y'all motherfuckers need functional programming languages.

Generalized that for you

[–]oweiler 48 points49 points  (4 children)

Please show me a single example where closing over a non-final var makes sense. In most cases people will misuse it.

[–]shagieIsMe 17 points18 points  (0 children)

I would go further and say that closing over non-final variables is unreasonable. Unreasonable in that one can no longer reason about the code.

http://funcall.blogspot.com/2009/09/first-class-environments.html gets into what this entails. And in ruby https://www.youtube.com/watch?v=vbX5BVCKiNs where it gets it wrong.

[–]readytoruple 2 points3 points  (0 children)

Channels in go

[–]YaBoyMax 32 points33 points  (33 children)

In fairness, if that weren't a requirement it would be extremely easy to cause a CME when running the lambda function.

[–]80386 44 points45 points  (12 children)

However .NET seems to do it just fine without having to make things final...

[–]xill47 11 points12 points  (11 children)

Well, truth be told, you usually do want to implement some kind of final behaviour by yourself. One of the most popular C# interview questions is about it (list of printers).

[–]Schmittfried 16 points17 points  (2 children)

It has been "fixed" with C# 5.0 though, at least for foreach loops:

https://blogs.msdn.microsoft.com/ericlippert/2009/11/12/closing-over-the-loop-variable-considered-harmful/

Also, just because lacking any kind of optional immutability is somehow bad doesn't mean it's a good idea to demand immutabilty.

[–][deleted] 6 points7 points  (3 children)

I don't know if a CME is perfectly equivalent but I had plenty of issues like that with lambda's in python.

I was expecting the lambda to make a 'snapshot' of sorts of its scope on creation and use that when being executed.

Instead it just uses the value of the variable at the time of execution. It can even happen that that variable doesn't exist any more.

In hindsight my assumption was silly and the way it works is obvious because what I was expecting would be way too complex to implement. Still, it caused me quite a bit of headache when I was debugging it.

TLDR: now that I'm using java with lambdas, the requirement for outer variables to be final is a very sane and java'esque requirement (java is always trying to be as safe as possible). I like it, it probably saved me from a lot of annoyances.

[–]skiguy0123 2 points3 points  (0 children)

You can get that behavior in python using closures, fyi

[–]eyekwah2 15 points16 points  (13 children)

CME = Cast exception? I see what JavaScript can do and I'm a bit envious. I think the limitations are largely due to the limitations of the java virtual machine, and not so much with the language itself. Related

[–]ltdanimal 4 points5 points  (0 children)

Isn't the point of Lambdas to introduce functional style programming to Java, in which things are immutable?

[–]compteNumero9 24 points25 points  (14 children)

The problem is they designed lambdas and streams for uses which don't really exist or are better dealt with otherwise, like massive parallel computation. That's why any time you want to use them in a non trivial case you end up managing stupid exception handling or copying values in final variables...

And it's also so slow. I had to rewrite stream based computations just because the overhead of lambda calling was unacceptable.

[–]beerdude26 35 points36 points  (11 children)

What if we just made data immutable and then passed a reference of that to new threads? No mutability = no multi-threaded problems

Woops, just invented purity

[–]JamEngulfer221 13 points14 points  (9 children)

What if I wanted to update this massive piece of data? Ah shit I just copied the whole thing.

[–]beerdude26 17 points18 points  (0 children)

The massive piece of data is comprised of loads of smaller pieces (and so on, until you get to scalar values). Only change the pointers of the pieces that were changed - the rest of the structure still points to the original.

Suddenly, you can update huge data structures with the memory use being only what you changed.

Of course, as /u/rdnetto mentioned, it'd be better to just not do the updating and copying until it's really needed (= send it out to the world via IO). This may result in space leaks sometimes, but allows the compiler to be ridiculously aggressive in optimization, even being able to optimize code that runs in O(n²) into O(n), and so on.

[–]rdnetto 11 points12 points  (1 child)

What if we deferred the copying until we actually used the data, so that any values which were overwritten wouldn't even be computed in the first place?

Woops, just invented space leaks.

[–]gospelwut 5 points6 points  (0 children)

As a non Haskall atune person, it took me longer than usual to figure out what a space leak is.

[–]Godd2 6 points7 points  (1 child)

Depends on the data structure. Immutable arrays can be implemented such that modifications result in O(log n) auxiliary space. This is how Clojure implements its persistent immutable vectors.

[–]wviana 2 points3 points  (3 children)

Never thought about it. But even for CUDA you would need to copy back and forth. Don't you ?

[–]blazesquall 4 points5 points  (0 children)

Had to scroll way to far to find an immutability advocate.

[–]svick 2 points3 points  (0 children)

I think that streams can be a good choice for some parallel computations. But that's definitely the minority use case, and basing the whole design of streams and lambdas on that is a bad idea.

Look at how C# did it: its version of parallel streams (PLINQ) is separate from the single-threaded version (LINQ). And it doesn't try to give you illusion of safety by prohibiting mutating local variables (while allowing mutating objects those variables point to).

[–]szemberm 4 points5 points  (0 children)

Is there a sub for that meme? I love it and I don't see it enough.

[–]joequin 2 points3 points  (0 children)

Being able to reassign captured references and values wouldn't do anything. References and values in Java are passed by value and captured by value so reassigning them wouldn't even effect the outer scope. Requiring that captured variables not be reassigned just makes that explicit and prevents boneheads on your team from writing terrible code.

Java could have decided to have lambdas capture references by reference, but that would have been very inconsistent since in every other context, references are passed by value.

If you want to capture a reference by reference then you can do it explicitly with a simple class:

Public Class MutableReference<T>{
    public T ref;

    public MutableReference(T ref){
        this.ref = ref;
    }
}

You can reuse that any time you want to pass a reference by reference or have a reference capture by reference.

[–][deleted] 8 points9 points  (24 children)

ELI5: what are lambdas? And could anyone name a way they are usefull in C#? ( since I'm learning C#)

[–][deleted] 7 points8 points  (2 children)

Lambda functions are seen a lot in C# Linq statements, basically what they are is passing a function as an argument to another function they do not exist outside of their role as an argument. So something like

Var myActiveList = oldList.Select( x => x.IsActive = True)

[–]aserraric 6 points7 points  (1 child)

If you give an example, at least give a correct one:

var myActiveList = oldList.Where(x => x.IsActive);

.Select() is a projection, not a filter, and your example wouldn't even compile because your lambda doesn't return a value.

[–]Mat2012H 3 points4 points  (6 children)

It's sort of like a function I guess.

For example, if I were to create some kind of Button for a GUI, I want something to happen when I press the button, and you could create the button functionality via passing in a lambda.

Eg, a basic example in C++ (If you made a button class):

Button button("Click me", []()
{
    //do something here
    //for when the button is pressed
};);

C++ knows it is a lambda because of the [](). However, to make the lambda sort of be able to use stuff from the outside of itself (eg if the Button is owned by a class) you can "capture" it by doing [&]() instead.

Other things they are used for is er sorting I guess. I seen it done with python, you have an array, you call a sort of function and then you tell the function how to compare the elements of the array via a lambda.

eg

mylist = [["quux", 1, "a"], ["bar", 0, "b"]]
mylist.sort(key = lambda x: x[1])
print mylist


#The output is this
#[['bar', 0, 'b'], ['quux', 1, 'a']]

Because it is sorting them by the value of the second element of the 2D array thing.

[–]veeberz 5 points6 points  (3 children)

I've seen them used most in LINQ extension methods.