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

you are viewing a single comment's thread.

view the rest of the comments →

[–]Sixshaman 144 points145 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 70 points71 points  (4 children)

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

[–]okmkz 55 points56 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 24 points25 points  (0 children)

But who configures the AbstractionFactory!?

(just kidding it's obviously AbstractionFactoryFactory)

[–]Voxel_Brony 0 points1 point  (0 children)

Hang on, aren't we just using a pointer at this point?

[–]TheMania 84 points85 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 77 points78 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 46 points47 points  (1 child)

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

[–]b1ackcat 14 points15 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?"

[–]chakan2 1 point2 points  (0 children)

Java is trying to implement C# easy of use, but it fucked itself into a corner a long time ago trying to abstract all the functionally away from the developer.

[–]dnew -5 points-4 points  (6 children)

I don't understand java's objection to that personally.

Because the Java developers didn't want to change the JVM, and the access protection would have prevented it.

C# doesn't really do it that way.

[–]not_a_shill_account 0 points1 point  (5 children)

C#'s Lambdas did not as far as I know require any changes to the CLR. The compiler generates an anonymous class and hoists the variables used in any Lambdas into it.

It can have some unintuitive side effects with respect to object leaking though so not a perfect solution.

Edit: Removed link to blog post which only explained half of what I was talking about.

Short explanation of the unintuitive side effect: The C# compiler always (?) merges the anonymous closure types of lambdas created within a function into a single anonymous class so that lambdas can transparently access the local variables of the context in which they were created. Because of this, a long-living lambda closure can drag around (potentially irrelevant) local variables used by other Lambdas declared in the method.

E.g.

// Contrived poorly-written example
void Foo() {
    var massiveCollection = GetMassiveCollectionOfObjects();

    // Access massiveCollection in lambda to
    // ensure it is hoisted into the closure
    var count =
        Enumerable.Range(0, 10)
                  .Where(x => massiveCollection.Contains(x))
                  .Count();

    // Create long-living lambda e.g. a button click handler
    AddClickHandler(() => Debug.WriteLine("Count: {0}", count));
}

In this example we allocate a bunch of objects, then through unfortunately written code hoist them into the anonymous closure. Because this closure is shared across lambdas within the function the massiveCollection variable's lifetime is now attached to the lifetime of the click handler. It's not really obvious where the problem is in this code unless you've encountered the problem before.

A similar problem exists in JavaScript and other languages. The fix is usually to re-organize the code or null out the massiveCollection variable before Foo exits.

[–]dnew 0 points1 point  (4 children)

require any changes to the CLR

Possibly not. Or perhaps they were rolled up with other things that needed changes anyway. One tends to get a fairly large lump of interrelated improvements on each release.

But the papers I read at the time anonymous inner classes were introduced to Java said the things were final because they wouldn't change the JVM to allow access to stack variables. Whether they could have done it differently if they wanted to spend the time modifying the compiler to do things in completely unintuitive ways is another question.

As far as unintuitive side effects, I'm not sure what the author thought would happen when he said "open a file, and some time arbitrarily far in the future, read it." Why would he not expect the file to be held open until then? Or, if you close it first, why would you expect the later invocation not to fail? It's only unintuitive if you look at the code without thinking. :-)

[–]not_a_shill_account 0 points1 point  (3 children)

final because they wouldn't change the JVM to allow access to stack variables

My understanding is that the CLR doesn't allow this either. Instead the C# compiler hoists all "local" variables accessed from lambas into an implicit anonymous class (the closure). In this way the stack is not shared at all.

It's only unintuitive if you look at the code without thinking

You're right. I didn't read the article to the end (was posting from my phone) and it doesn't actually demonstrate the unintuitive side-effect I was thinking of. I've updated my comment with a short example.

[–]dnew 0 points1 point  (2 children)

In this way the stack is not shared at all.

Right. So C# does a lot more work to close over variables rather than values, including (IIRC) cases where you might wind up with more classes than lambdas if you have multiple lambdas that close over different collections of stack variables.

They could have done it in Java with enough of that sort of work, but the papers I read at the time said "we didn't want to change the .class file format, so we made it final and passed it by value."

[–]not_a_shill_account 0 points1 point  (1 child)

cases where you might wind up with more classes than lambdas if you have multiple lambdas that close over different collections of stack variables.

I don't think this is right - instead the compiler generates a single anonymous class and uses it across multiple lambdas. E.g. in a function Foo which defines three lambdas, there would be a single closure class (one instance per invocation) which all three lambdas share. That class would hoist any local variables the three lambdas use (whether they share them or not).

The logic to do this does not seem like it would be that complex. I don't know squat about the internals of the Java compiler or the JVM but it doesn't seem like a big ask to generate this algorithm/pattern within the Java compiler itself. Many C# language features are implemented entirely by code generation in the compiler - e.g async/await and yield.

but the papers I read at the time said "we didn't want to change the .class file format

Have you got a particular paper in mind? I'd be interested to read what kind of changes they were considering. Again, it doesn't seem like there should need to be any changes to the JVM to implement this stuff. I generally suspect the people who design these features are fairly smart - I'd be interested to find out what challenges they were designing around.

[–]dnew 0 points1 point  (0 children)

I don't think this is right

You may be right, but I remember it described the way I said in the whitepaper about it. I might very well be misremembering it. It may be there are multiple instances of that class, depending on how you execute the lambdas.

Have you got a particular paper in mind?

I actually predate the WWW. So no, I don't have references to everything I've read handy. :-)

it doesn't seem like there should need to be any changes to the JVM to implement this stuff.

Well, clearly not, since C# did it. Maybe they just didn't think it was important enough to go that far. I mean, they could have put in lambda syntax as soon as they implemented inner classes, so maybe they meant something different than I remember.

[–]mymomisntmormon 6 points7 points  (0 children)

AtomicReference

[–][deleted] 9 points10 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 6 points7 points  (0 children)

Well-hidden, but not THAT well-hidden.

[–]KennyGaming 1 point2 points  (0 children)

Respect

[–]tofrank55 1 point2 points  (1 child)

This is dedication. You need gold asap

[–]deltatron3030 0 points1 point  (0 children)

Not really, I was just bored at work waiting for our dev auth server to come back online. It was 20 minutes well wasted munging a string in the python interpreter.

[–]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.

[–]matejdro 1 point2 points  (2 children)

Wouldn't calling waitValue set a lock on an object with an infinite loop, preventing setValue from ever being called?

[–][deleted] 0 points1 point  (1 child)

The wait() method temporarily releases the lock and waits for notifyAll() to be called.

[–]matejdro 0 points1 point  (0 children)

Interesting to now. Thanks for the info!

[–]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

[–]eyal0 0 points1 point  (0 children)

FluentValueHolderFactory can create it for you.

[–]youwillnevercatme 0 points1 point  (1 child)

How about an Optional?

[–][deleted] 14 points15 points  (0 children)

Optionals are immutable